UIImageView pixel-perfect `touches began` for non-transparent parts of UIImage - iphone

developing iphone app, I have used a UIImageview and i have set an image of irregular shape
// uiimageview type shutter
shutter = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,32.5)];
//setting image on shutter
UIImage* shutterimg = [UIImage imageNamed:#"trayshutter.png"];
[shutter setImage:shutterimg];
// User interaction
shutter.userInteractionEnabled=YES;
and i get touches using touchesbegan
everything is fine, but issue is I also get events in all the rectangle area occupied by the CGRectMake (i.e. 0,0,320,32.5) of imageview, whereas i require events only on the image (which is of shape of -----|||||-----).
How can i make sure that i get events only on the image and not on the rest of area covered by cgrectmake ?

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch view] == yourDesiredImage) {
// Do something here
}
}
EDIT: maybe you can try UITapGestureRecognizer instead:
UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
[tapGestureRecognizer addTarget:self action:#selector(yourTouchMethod:)];
[tapGestureRecognizer setNumberOfTapsRequired:1];
[shutter addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

Related

Detect touch of UIImage added as subview of UIScrollView

I have UIScrollView with many UIImageViews.I need to drag and drop image from UIScrollView to another view. Outside the scrollView touch is worked. But inside scroll view touch is not worked. I used touchesBegan,touchesMoved etc method. Please help me.
-(IBAction)selectBut:(id)sender
{
scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(x,y,w,h)];
scrollView.userInteractionEnabled = YES;
int y = 0;
for (int i = 0; i < [myArray count]; i++) {
UIImageView *image = [[UIImageView alloc]initWithFrame:CGRectMake(0, y, 75, 30)];
image.userInteractionEnabled = YES;
y=y+35;
[scrollView addSubview:image];
}
[self.view addSubview:scrollView];
[scrollView setContentSize:CGSizeMake(150, 300)]
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 1) {
NSLog(#"One touch !!");
}
}
you need to customize the UIImageView with your own view inherited from UIImageView. Provide touch methods in that customized subclass and add it on your UIScrollView..
Subviews of UIScrollview will never call touchesBegan method directly. You need to customized with subview to get touchesBegan properties of that added subview/customized view.
I mean to say take subclass of ImageView like
CustomImageView *imageView = [[CustomImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[imageView setUserInteractionEnabled:YES];
[scrollView addSubview:imageView];
[imageView release];
CustomImageView class is should be inherited from UIImageView like
#interface CustomImageView : UIImageView
{
}
in # .m File
#import "CustomImageView.h"
#implementation CustomImageView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"%s", __FUNCTION__);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
drawImageView.image = nil;
return;
}
}
Add a Tap gesture recognizer to the scroll view for enabling touch inside scroll view:
UITapGestureRecognizer *singlTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(methodName:)];
singlTap.cancelsTouchesInView = NO; //Default value for cancelsTouchesInView is YES, which will prevent buttons to be clicked
[scrollViewName addGestureRecognizer:singlTap];
then write your code in specified method.
-(void)methodName:(UITapGestureRecognizer *)gesture
{
//your code here
}
I don't know if this help you. But try to set the exclusiveTouch property of the UIImageView to YES.
Did you add your scrollview as an IBOutlet? If its from xib and as you say touches are available outside the scroll and not within, I guess you might have accidentally unchecked userInteractionEnabled for the scrollview which inhibits touch events. And you have added UIImageViews as subviews to UIScrollView. For UIImageView you have to first set userInteractionEnabled to YES and then add any gestures if necessary to get events or use the touchesBegan, touchesMoved methods. Unless you set interaction enabled you wont receive touch events on UIImageView. If the parent view I mean the UIScrollView's interaction is disabled you wont get touches on UIImageView too. Hope this helps :)

How to call touchesBegan on a layer that is a sublayer of a UIWebView

I have a layer that I have added as a sublayer of a UIWebView. I would like to be able to touch and drag the layer around. Before I added the UIWebView, I was able to touch and drag around the layer without a problem.
Here's where I create the layer and add it as a sublayer
- (void)viewDidLoad
{
[super viewDidLoad];
starLayer = [CALayer layer];
starLayer.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage
imageNamed:#"star"]].CGColor;
starLayer.shadowOffset = CGSizeMake(0, 3);
starLayer.shadowRadius = 5.0;
starLayer.shadowColor = [UIColor blackColor].CGColor;
starLayer.shadowOpacity = 0.8;
starLayer.frame = CGRectMake(235.0, 200.0, 35.0, 35.0);
[self.aboutWebView.layer addSublayer:starLayer];
[self moveStar];
}
Here's my moveStar method
- (void)moveStar
{
CAKeyframeAnimation *move = [CAKeyframeAnimation animationWithKeyPath:#"position"];
NSMutableArray *values = [NSMutableArray array];
[values addObject:[NSValue valueWithCGPoint:CGPointMake(250.0, 50.0)]];
[values addObject:[NSValue valueWithCGPoint:CGPointMake(250.0, 250.0)]];
[move setValues:values];
[move setDuration:1.0];
[move setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
// Add the animation to the layer to be animated
[starLayer addAnimation:move forKey:#"moveAnimation"];
}
So far so good. The star falls onto the screen and lands a bit above the middle. But when I try and touch the star nothing happens. touchesBegan never gets called for some reason.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.aboutWebView];
[starLayer setPosition:point];
}
Is the reason I can't touch the star when it's a sublayer of aboutWebView because a touch is reported to a view, not a layer?
Does anyone have any suggestions on how to make the star as a sublayer of aboutWebView touchable? Is it possible?
Thank you!
In your layer... try to set the UIGestureRecognizer property cancelsTouchesInView to NO.
"Setting this value to NO instructs the recognizer to deliver all touches to the underlying view, even when it has recognized the sequence"
something like that:
UIGestureRecognizer *touches = [UIGestureRecognizer alloc];
//or
//UIGestureRecognizer *touches = [[UIGestureRecognizer alloc] initWithTarget:self action:#selector(touchesAction:)];
touches.enabled=YES;
[yourLayer addGestureRecognizer:touches];
touches.cancelsTouchesInView=NO;

iOS CGRectIntersectsRect with multiple instances of UIImageView?

I have a layout for an application that needs to detect when an image collides with another image.
Here, the user creates multiple 'balls', the same instance of a UIImageView named 'imgView', on the screen by tapping the location they desire:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [[event allTouches] anyObject];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 40, 40, 40)];
imgView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imgView];
imgView.center = [myTouch locationInView:self.view];
}
(imgView is declared as a UIImageView in the header) :
UIImageView *imgView;
Now, I also have an image called 'staff'. It is a long bar that pans horizontally across the screen. I want the image 'staff' to detect EVERY collision it has with the variable 'imgView', or the balls the user has placed on the screen.
Therefore, the user could tap 10 different places on the screen and and 'staff' should be able to catch every single one.
I use this CGRectIntersectsRect code thats activated by an NSTimer:
-(void)checkCollision {
if( CGRectIntersectsRect(staff.frame,imgView.frame)) {
[self playSound];
}
}
However, the intersection is only detected with the LAST instance, or 'ball' the user created. The staff reacts to that one, but pans over the rest. Any help to fix my code to detect all instances would be greatly appreciated.
Each time you create a new ball, you are overriding your imgView instance variable. Thus, your checkCollision method only sees the latest value of imgView, namely the last ball created.
Instead, you could keep track of every ball on screen in an NSArray, then check for collisions against every element in that array. To do that, replace your imgView instance variable with, say:
NSMutableArray *imgViews
Then, sometime early on, say in viewDidLoad initialize the array:
imgViews = [[NSMutableArray alloc] init]
In -touchesEnded:withEvent: add the new UIImageView to the array:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *myTouch = [[event allTouches] anyObject];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 40, 40, 40)];
imgView.image = [UIImage imageNamed:#"ball.png"];
[self.view addSubview:imgView];
imgView.center = [myTouch locationInView:self.view];
[imgViews addObject:imgView]
}
And finally, in checkCollision iterate through your array and perform your check on every element
- (void)checkCollision {
for (UIImageView *imgView in imgViews) {
if( CGRectIntersectsRect(staff.frame,imgView.frame)) {
[self playSound];
}
}

Touch event on uimageview added as subview to parent view

I have added the view programmatically in the main view. And in the parent view i am adding imageview as a subview programmatically. Now I have set the touch event for imageview on click but its not working. It is not detecting the touch event on click. I am using the following code of touch event of imageview.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch view] == originalphoto)
{
[fullview setHidden:NO];
[self.view addSubview:fullview];
[setimage setImage:image];
}
}
Do anyone has idea that how to set touch event of imageview which has been added programmatically?
Thanks alot.
Why dont you use a gesture? it is lot easier. You could use the UITapGestureRecognizer and let it work for you: http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UITapGestureRecognizer_Class/Reference/Reference.html
//Add gesture to your view
UITapGestureRecognizer *Tap= [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(ResignResponder:)];
[tempV addGestureRecognizer:Tap];
[Tap release];
//method will be called on tapping the view
-(void)ResignResponder:(UIGestureRecognizer*)recognizer {
[LocSearchField resignFirstResponder];
[self.view sendSubviewToBack:tempV];
}
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:UIIMAGEVIEW];// uiimageview object
touchx = location.x;
touchy = location.y;
NSLog(#" x= %i ", touchx);
NSLog(#"y = %i",touchy);
Maybe you need to set property imageView.userInteractionEnabled = YES?

How can i associate an IBAction event with an image?

I have a application which contains a moving image and i want to animate the image using a my custom animation.
How can i associate an IBAction event with the image?
How can i detect the coordinates on screen where the user touched the image?
Please Give Your Suggestions.
Thanks in advance and Your Suggestions are Most Welcome.
You could use custom UIButtons with your image. All the touch handling code is already builtin.
Edit: UIGestureRecognizer also work on UIImageViews:
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"foo.png"]] autorelease];
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction:)] autorelease];
[imageView addGestureRecognizer:tapGesture];
[self.view addSubview:imageView];
You can also do this way:
first define the rect where you image will be:
touchRect=CGRectMake(screen.width/2-screen.width/8, 0, screen.width/4, screen.height/5);
then with touchesEnded method you can define what you want to do when you touch over that zone:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint targetPoint = [[touches anyObject] locationInView:self];
if (CGRectContainsPoint(touchRect, targetPoint)){
//YOUR CODE HERE
}
}