弹幕容器和手势:LNDanmakuContainerView

2021-02-05  本文已影响0人  BangRaJun

这篇文章的前置文章:LNDanmakuMaster

弹幕容器通常需要覆盖在播放器视图上面,容器需要响应那些有弹幕区域的手势,透传那些没有弹幕区域的手势;如果希望使用CALayer系列组件做动效就需要额外处理手势,因为通常CALayer是不能响应手势,所以,我将这些繁琐的处理封装成ContainerView进行统一处理。

处理后的ContainerView有如下特性:

hitTest函数是ContainerView处理手势的核心代码:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (self.hidden) {
        return [super hitTest:point withEvent:event];
    }
    for (CALayer *layer in [self.layer.sublayers reverseObjectEnumerator]) {
        if ([layer hitTest:point]) {
            if (layer.danmakuAttributes) {
                return self;
            } else {
                return [super hitTest:point withEvent:event];
            }
            break;
        }
    }
    return nil;
}

判断流程如下:

注:倒序遍历,因为调用addSubview/addSubLayer在不刻意设置zPosition时,后加入的View/Layer通常覆盖在前面加入的View/Layer上,所以,倒序遍历的结果会更符合用户视觉上的认知。

用户触发手势后走didTapped函数,这个函数的主要工作目标是找到Attributes并通过代理把这个事件传出去:

- (void)didTapped:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:self];
    CALayer *tappedLayer = nil;
    UIView *tappedView = nil;
    for (CALayer *layer in [self.layer.sublayers reverseObjectEnumerator]) {
        if ([layer hitTest:point]) {
            if (layer.danmakuAttributes) {
                tappedLayer = layer;
            } else {
                if ([layer.delegate isKindOfClass:[UIView class]]) {
                    tappedView = (UIView *)layer.delegate;
                }
            }
            break;
        }
    }

    LNDanmakuAbstractAttributes *targetAttributes;
    if (tappedLayer) {
        targetAttributes = [tappedLayer danmakuAttributes];
    } else if (tappedView) {
        targetAttributes = [tappedView danmakuAttributes];
    }
    
    if (targetAttributes && self.delegate && [self.delegate respondsToSelector:@selector(danmakuContainerDidTappedAttributes:)]) {
        [self.delegate danmakuContainerDidTappedAttributes:targetAttributes];
    }
}

(这里应该先判断是否有代理,没有代理可以直接return,免得做多余的计算,之后改一下)

建议:除了弹幕视图之外最好不要在containerView上加其他的视图,加在containerView的父视图上。

上一篇下一篇

猜你喜欢

热点阅读