【发布时间】:2015-10-05 07:55:40
【问题描述】:
【问题讨论】:
标签: ios swift uibutton hittest
【问题讨论】:
标签: ios swift uibutton hittest
这个想法是有一个 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 方法)。
【讨论】:
最好为 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
}
}
【讨论】:
其实我是在这样的地方找到的,而且效果很好:
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
}
【讨论】: