美文网首页
iOS swift UIView及其Subview通过透明度的判

iOS swift UIView及其Subview通过透明度的判

作者: 彭磊PL | 来源:发表于2020-07-16 12:07 被阅读0次

    背景

    在开发过程中会有这样一种场景:在一个页面A上弹出了一个透明或者半透明的view B,希望在点击ViewB的透明或者半透明区域的时候,将点击事件透传给下层页面A。废话不说啦,请看代码

           override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
                let alpha = alphaOfPoint(point: point)
                // 处于当前view及sub view的点击位置颜色的alpha值大于阈值,则事件不穿透,否则就透传
                if alpha > DuPoplayerWKWebview.alphaThreshold {
                    return true
                }else {
                    return false
                }
            }
            
            func alphaOfPoint(point: CGPoint) -> CGFloat {
                return alphaOfPointFromLayer(point: point)
            }
            
            
            func alphaOfPointFromLayer(point: CGPoint) -> CGFloat {
                var pixel = [UInt8](repeatElement(0, count: 4))
        //        var pixel: [UInt8] = [0, 0, 0, 0]
                let colorSpace = CGColorSpaceCreateDeviceRGB()
                let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
                context?.setBlendMode(.copy)
                context?.translateBy(x: -point.x, y: -point.y)
                if let context = context {
                    layer.render(in: context)
                }
                let alpha = CGFloat(pixel[3]) / CGFloat(255.0)
                
                return alpha
            }
            
            override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
                if self.point(inside: point, with: event) {
                    return super.hitTest(point, with: event)
                }
                guard isUserInteractionEnabled, !isHidden, alpha > 0 else {
                    return nil
                }
    
                for subview in subviews.reversed() {
                    let convertedPoint = subview.convert(point, from: self)
                    if let hitView = subview.hitTest(convertedPoint, with: event) {
                        return hitView
                    }
                }
                return nil
            }
    

    hitTest:withEvent:方法大致处理流程是这样的:

    • 首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内:
    • 若pointInside:withEvent:方法返回NO,说明触摸点不在当前视图内,则当前视图的hitTest:withEvent:返回nil
    • 若pointInside:withEvent:方法返回YES,说明触摸点在当前视图内,则遍历当前视图的所有子视图(subviews),调用子视图的hitTest:withEvent:方法重复前面的步骤,子视图的遍历顺序是从top到bottom,即从subviews数组的末尾向前遍历,直到有子视图的hitTest:withEvent:方法返回非空对象或者全部子视图遍历完毕。

    最后附上Demo

    相关文章

      网友评论

          本文标题:iOS swift UIView及其Subview通过透明度的判

          本文链接:https://www.haomeiwen.com/subject/mpkphktx.html