How to know that if the only visible area of a .png is touched in Xcode
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
}
How to check whether a CGPoint is inside a UIImageView?
Sounds to me like the problem is you need to convert coordinates from your view's coordinates to the UIImageView
's coordinates. You can use UIView
's convertPoint
method.
Try replacing
if ([image pointInside:touch_point withEvent:event]) {
with
if ([image pointInside: [self.view convertPoint:touch_point toView: image] withEvent:event]) {
(Note that you are allowed to pass nil
instead of event
.)
I guess this is a bit late for the questioner, but I hope it is of use to someone.
Custom shape touchable area
Actually I found it on this like and working perfectly:
How to know that if the only visible area of a .png is touched in XCode (swift or objective C)
But must change code like below:
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
}
Detect if a layer that uses a transform contains a touch point
I found an alternate solution. SpaceDog got me thinking about the situation differently. I just need to know if an area with color is touched. I found this post and translated it to Objective C. It works beautifully. While I would prefer the detection of the point was within the arrow, this should work for my purposes just as well. Thanks for y'all's reply. I appreciate it.
Post I got the code below from.
- (void) tapped: (UITapGestureRecognizer *) sender {
CGPoint location = [sender locationInView: sender.view];
CGFloat p = [self alphaFromPoint:location];
if (p > 0) {
[_delegate arrowTouched:self];
}
}
- (CGFloat) alphaFromPoint: (CGPoint) point {
UInt8 pixel[4] = {0,0,0,0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo alphaInfo = (CGBitmapInfo)kCGImageAlphaPremultipliedLast;
CGContextRef context = CGBitmapContextCreate(&pixel, 1, 1, 8, 4, colorSpace, alphaInfo);
CGContextTranslateCTM(context, -point.x, -point.y);
[self.layer renderInContext:context];
CGFloat floatAlpha = pixel[3];
return floatAlpha;
}
How to invoke method on click on only visible part of animage view
Have a look at github for the OBSHAPED button .it will resolve your problem Happy coding.:)
How to make the frame of a button custom shape in Swift 2
Here is an example of a button that only responds to touches within a certain area.
class MyButton: UIButton {
var path: UIBezierPath!
override func awakeFromNib() {
backgroundColor = UIColor.greenColor()
addTarget(self, action: #selector(touchDown), forControlEvents: .TouchDown)
}
override func drawRect(rect: CGRect) {
path = UIBezierPath()
path.moveToPoint(CGPointMake(150, 10))
path.addLineToPoint(CGPointMake(200, 10))
path.addLineToPoint(CGPointMake(150, 100))
path.addLineToPoint(CGPointMake(100, 100))
path.closePath()
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = UIColor.redColor().CGColor
shapeLayer.fillColor = UIColor.blueColor().CGColor
shapeLayer.path = path.CGPath
layer.addSublayer(shapeLayer)
}
func touchDown(button: MyButton, event: UIEvent) {
if let touch = event.touchesForView(button)?.first {
let location = touch.locationInView(button)
if path.containsPoint(location) == false {
button.cancelTrackingWithEvent(nil)
}
}
}
}
Related Topics
iOS 9 '-Webkit-Overflow-Scrolling:Touch' and 'Overflow: Scroll' Breaks Scrolling Capability
Getting Back a Date from a String
iPhone Simulator Suddenly Started Running Very Slow
What Tool(S) How to Use to Produce iPhone App Screencasts
Get the Current View Controller from the App Delegate
Ios: How to Find the Creation Date of a File
How to Create Auto Incremented Key in Firebase
CSS Styled Scrollbars Support for Safari Mobile on iOS 6 Disappeared
How to Disable the Network in iOS Simulator
Completion Handler for Uinavigationcontroller "Pushviewcontroller:Animated"
Uiscrollview with Centered Uiimageview, Like Photos App
Swift Merge Audio and Video Files into One Video
How to Use Static Cells in Uitableview Without Using Storyboards