【问题标题】:Custom shape touchable area自定义形状可触摸区域
【发布时间】:2015-10-05 07:55:40
【问题描述】:

我有一个像下面这样的形状,我想将它设置为我的 UIButton 的背景 但是 可触摸区域是一个矩形, 有什么建议可以改变可触摸区域来塑造寄宿生吗?

【问题讨论】:

    标签: ios swift uibutton hittest


    【解决方案1】:

    这个想法是有一个 UIButton 的子类覆盖以下方法:

    func hitTest(_ point: CGPoint,
       withEvent event: UIEvent?) -> UIView? // that's for handling the case of multiple custom subviews on your view rather than for evaluating if it's your view to handle the touch
    

    func pointInside(_ point: CGPoint,
           withEvent event: UIEvent?) -> Bool // way more preferable than hit test in your case!!!
    

    Objective-C 中有一个使用命中测试的教程(只是为了抓住这个想法)。在您的情况下,最困难的问题是检测接收到的触摸位置是否在您的自定义形状的范围内(上面的教程依赖于像素透明度,您的情况并非如此)。我假设,您使用贝塞尔路径绘制形状。如果这就是您所做的,您可以使用 UIBezierPath 的 func containsPoint(_ point: CGPoint) -> Bool 实现内部评估点。祝你好运。 P.S.UIBezierPath 还有一个棘手的问题:

    如果一个点在内部,则不认为它被路径包围 一个开放的子路径,无论该区域是否会被绘制 在填充操作期间。因此,要确定鼠标点击打开 路径,您必须创建路径对象的副本并显式关闭 调用此方法之前的任何子路径(使用 closePath 方法)。

    【讨论】:

    • 感谢您的建议
    【解决方案2】:

    斯威夫特 4.2

    最好为 UIButton 写一个扩展。重写 touchesBegan 函数,检查触摸区域是否透明。

    extension UIButton{
    
        open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            if let touch = event!.touches(for: self)?.first {
                let location = touch.location(in: self)
                if alphaFromPoint(point: location) == 0 {
                    self.cancelTracking(with: nil)
                    print("cancelled!")
                } else{
                    super.touchesBegan(touches, with: event)
                }
            }
        }
    
        func alphaFromPoint(point: CGPoint) -> CGFloat {
            var pixel: [UInt8] = [0, 0, 0, 0]
            let colorSpace = CGColorSpaceCreateDeviceRGB();
            let alphaInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
            let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: alphaInfo.rawValue)
    
            context!.translateBy(x: -point.x, y: -point.y)
            self.layer.render(in: context!)
    
            let floatAlpha = CGFloat(pixel[3])
            return floatAlpha
        }
    }
    

    【讨论】:

      【解决方案3】:

      其实我是在这样的地方找到的,而且效果很好:

      How to know that if the only visible area of a .png is touched in XCode (swift or objective C)

      必须更改如下代码:

         func alphaFromPoint(point: CGPoint) -> CGFloat {
         var pixel: [UInt8] = [0, 0, 0, 0]
         let colorSpace = CGColorSpaceCreateDeviceRGB();
         let alphaInfo : CGBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue)
         let context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, colorSpace, alphaInfo.rawValue) //need add .rawValue to alphaInfo
      
         CGContextTranslateCTM(context, -point.x, -point.y);
      
         self.layer.renderInContext(context!)
      
         let floatAlpha = CGFloat(pixel[3])
         return floatAlpha
      

      }

      【讨论】:

      • 为了在点击时忽略高亮,我们需要设置 btnCustom.adjustsImageWhenHighlighted = false
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-09
      • 2018-07-03
      • 2018-12-18
      相关资源
      最近更新 更多