UIButton高亮无效问题

372 阅读1分钟

当UIButton的父容器有ScrollView的时候,button的点击高亮效果会失效,快速设置了highlighted = YES, highlighted = NO, 中间基本没时间间隔,所以看到不效果

分析:

UIScrollView 有个属性 delaysContentTouches,该值默认为 YES,属性的意思是 scrollView 在接收到手势时会延迟 300ms 来判断该手势是否能够触发 scrollView 的滑动事件;值为 NO 时 scrollView 会立刻将手势分发到子视图上。事件分发机制

设置 delaysContentTouches 为 NO 又会造成另外一个问题,如果拖动 scrollView 的手势触发到其他手势的视图上那么 scrollView 无法触发滚动事件

最简单解决方案:延迟设置高亮状态

@import ObjectiveC;

@implementation UIControl (TT_Control_Highlight)

+ (void)TT_exchangeMethod {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class clz = UIControl.class;
        Method m0 = class_getInstanceMethod(clz, @selector(endTrackingWithTouch:withEvent:));
        Method m1 = class_getInstanceMethod(clz, @selector(TT_endTrackingWithTouch:withEvent:));
        NSParameterAssert(m0 && m1);
        if (m0 && m1) {
            method_exchangeImplementations(m0, m1);
        }
    });
}

- (BOOL)TT_useHighlight {
    return [objc_getAssociatedObject(self, @selector(setTT_useHighlight:)) boolValue];
}

- (void)setTT_useHighlight:(BOOL)TT_useHighlight {
    objc_setAssociatedObject(self, _cmd, @(TT_useHighlight), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (TT_useHighlight) {
        [self.class TT_exchangeMethod];
    }
}

- (void)TT_endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    [self TT_endTrackingWithTouch:touch withEvent:event];
    if (!self.TT_useHighlight) {
        return;
    }
    if (!self.highlighted) {
        return;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        self.highlighted = YES;
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.highlighted = NO;
    });
}

@end
···