I have imported a .png image into UIImageView
in Xcode and what I want to make is when the image is touched, it will be hidden.
But my problem is that
I have created a custom UIButton subclass that behaves exactly as you describe, have a look: https://github.com/spagosx/iOS-Shaped-Button-Swift
It's written in Swift, but it's easily convertible to Objective-c.
The approach is to get the pixel data from the touch point and to access the RGBA values, in this case we read A (alpha) and check if it is higher than our threshold.
Looking at a bit of code:
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
}
You can than take the floatAlpha
value and compare it with your acceptable value of alpha:
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
return self.alphaFromPoint(point) >= 100
}
Combining Danny's and Sport's answer in Swift 4.2 as an extension.
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
}
}
I have taken the liberty of updating 'Danny S's' answer to Swift 5 and removed extraneous code, bug fixed and added some additional clarity to the UX.
Here's the code:
https://github.com/ZoeESummers/SOXShapedTapView-Updated.git
-(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
}
}