如何知道是否在 Xcode 中触摸了 .png 的唯一可见区域

How to know that if the only visible area of a .png is touched in Xcode

我在 Xcode 中将一个 .png 图像导入到 UIImageView 中,我想要做的是当图像被触摸时,它会被隐藏。

但我的问题是 png 图像包含透明部分,当我触摸透明部分时,动作继续进行。我希望只有当图像的可见部分被触摸时,动作才会继续。如何解决问题?

Swift 或 Objective-C

  -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    {
        UITouch *touch = [touches anyObject]; 
        CGPoint touch_point = [touch locationInView:self.view];

        if (![imageView pointInside:touch_point withEvent:event]) 
        {
            NSLog(@"you inside imageview");
// write here what you want
        }
    } 

我已经创建了一个自定义的 UIButton 子类,其行为与您描述的完全一样,请看一下:https://github.com/spagosx/iOS-Shaped-Button-Swift

它是用 Swift 写的,但很容易转换为 Objective-c。

方法是从触摸点获取像素数据并访问 RGBA 值,在本例中我们读取 A (alpha) 并检查它是否高于我们的阈值。

查看一些代码:

func alphaFromPoint(point: CGPoint) -> CGFloat {
    var pixel: [UInt8] = [0, 0, 0, 0]
    let colourSpace = CGColorSpaceCreateDeviceRGB()
    let alphaInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
    let context = CGContext(data: &pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colourSpace, bitmapInfo: alphaInfo.rawValue)

    context?.translateBy(x: -point.x, y: -point.y)

    self.layer.render(in: context!)

    let floatAlpha = CGFloat(pixel[3])
    return floatAlpha
}

您可以取 floatAlpha 值并将其与您可接受的 alpha 值进行比较:

    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
        return self.alphaFromPoint(point) >= 100
    }

在 Swift 4.2 中合并 Danny 和 Sport 的回答作为扩展。

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
    }
}

我冒昧地更新了“Danny S”对 Swift5 的回答并删除了无关代码,修复了错误并为用户体验增加了一些额外的清晰度。

代码如下:

https://github.com/ZoeESummers/SOXShapedTapView-Updated.git