答案 0 :(得分:2)
我们的想法是拥有一个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中有一个使用命中测试的教程(只是为了捕捉这个想法)。在您的情况下,最难的问题是检测接收的触摸位置是否在您的自定义形状的范围内(上面的教程依赖于像素透明度,而不是您的情况)。我假设你使用Bezier路径绘制形状。如果这就是您所做的,您可以使用UIBezierPath的func containsPoint(_ point: CGPoint) -> Bool
实现评估中的点。祝好运。
P.S.关于UIBezierPath还有一个棘手的问题:
如果一个点在里面,则不认为该点被路径包围 一个开放的子路径,无论该区域是否被绘制 在填充操作期间。因此,确定打开时的鼠标命中 路径,您必须创建路径对象的副本并显式关闭 调用此方法之前的任何子路径(使用closePath方法)。
答案 1 :(得分:0)
实际上我发现它就像这样并且工作得很好:
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
}
答案 2 :(得分:0)
最好为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
}
}