YYLabel 重用时出现内容“闪现”

原文链接

原因

YYLabel 为了有更好的用户体验在内容展示加了一个渐变动画。这个动画是由contentsNeedFade控制的(这里不讨论异步渲染的情况)。在没有点击的情况下contentsNeedFade是处于关闭状态的,如果触发内容点击操作,那么contentsNeedFade 则会被打开。此时 YYLable 被重用的话就会出现内容 “闪现” 的问题(这个闪现其实就是这个渐变动画)。

作者给开发者一个关闭这个动画的属性fadeOnHighlight,只要设置为NO即可避免重用的闪现问题。不幸的是在用户触摸时取消触摸事件(即触发:touchesCancelled:withEvent:)的情况下依然会出现闪现问题。这是因为在_endTouch方法里面的 _removeHighlightAnimated 是直接写死 YES 的,这导致了contentsNeedFade 被迫打开,最终造成了重用闪现的问题。具体源码如下:

// YYLabel.m
- (void)_endTouch {
    [self _endLongPressTimer];
    [self _removeHighlightAnimated:YES];
    _state.trackingTouch = NO;
}

解决

解决这问题也很简单,代码如下:

// YYLabel.m 
- (void)_endTouch {
    [self _endLongPressTimer];
    [self _removeHighlightAnimated:_fadeOnHighlight];
    _state.trackingTouch = NO;
}

本人最近也提交了Pull requests

测试 Demo: YYLabelFadeBug

闪现场景 1

  1. 注释 //_contentLabel.fadeOnHighlight = NO; 触发点击
  2. 滑动列表即可出现内容闪现问题

闪现场景 2

  1. 取消注释 _contentLabel.fadeOnHighlight = NO;
  2. 先点击内容,然后手指往下滑触发点击取消
  3. 滑动列表即可出现内容闪现问题

更新

由于房间公屏增加了长按@人功能,所以使用了 YYLabel 的长按功能。意想不到的是 YYLabel 重用时也出现内容闪现问题。原因跟上述一样,所以修复方式相同。具体修复如下

- (void)_trackDidLongPress {
    [self _endLongPressTimer];
    if (_state.hasLongPressAction && _textLongPressAction) {
        NSRange range = NSMakeRange(NSNotFound, 0);
        CGRect rect = CGRectNull;
        CGPoint point = [self _convertPointToLayout:_touchBeganPoint];
        YYTextRange *textRange = [self._innerLayout textRangeAtPoint:point];
        CGRect textRect = [self._innerLayout rectForRange:textRange];
        textRect = [self _convertRectFromLayout:textRect];
        if (textRange) {
            range = textRange.asRange;
            rect = textRect;
        }
        _textLongPressAction(self, _innerText, range, rect);
    }
    if (_highlight) {
        YYTextAction longPressAction = _highlight.longPressAction ? _highlight.longPressAction : _highlightLongPressAction;
        if (longPressAction) {
            YYTextPosition *start = [YYTextPosition positionWithOffset:_highlightRange.location];
            YYTextPosition *end = [YYTextPosition positionWithOffset:_highlightRange.location + _highlightRange.length affinity:YYTextAffinityBackward];
            YYTextRange *range = [YYTextRange rangeWithStart:start end:end];
            CGRect rect = [self._innerLayout rectForRange:range];
            rect = [self _convertRectFromLayout:rect];
            longPressAction(self, _innerText, _highlightRange, rect);
            // [self _removeHighlightAnimated:YES];
            // 修复如下
            [self _removeHighlightAnimated:_fadeOnHighlight];
            _state.trackingTouch = NO;
        }
    }
}

你可能感兴趣的:(YYLabel 重用时出现内容“闪现”)