Why doesn't the touch event arrive at my UIImageView? - iphone

I have some nested views like this:
First, there is an big UIView. Inside this, there is another UIView. And inside this, there is an MyNiceButtons class that inherits from UIView. So I have:
UIView > UIView > MyNiceButtons (= an UIView).
In detail, the UIView creates an UIImageView and adds it as a child view to itself, which represents an graphical button. So inside the MyNiceButtons class implementation, I have this code to handle a touch event on the fake button image:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject]; // i just need single touches
// just to see which view is affected
UIView *tview = [touch view];
CGRect rect = tview.frame;
rect.origin.x = rect.origin.x + 20.0f;
tview.frame = rect;
[tview setBackgroundColor:[UIColor yellowColor]];
if ([touch view] == self.fakeButtonImageView) {
NSLog(#"touch on fake button detected");
}
}
All views in the hierarchy have userInteractionEnabled=YES. The touch arrives at the first view in the hierarchy (the parent of the parent).
UIView *tview = [touch view];
This returns just the parent of the parent, but not the UIImageView where the user actually tapped on.
What's the trick to recognize if the touch was on the button UIImageView?

I would first suggest that you take a good look at what you can do with a Custom-type UIButton (can set images for various states). 95% of the time, this should address your needs.
If you have some other need, I can help you debug w/ hitTest, etc.

Related

Bring UIImageView on top of the other UIImageViews in my main view

I have a lot of UIImageViews in my main view, some of these have images, others are blank. I have setup code that will check which UIImageView currently contains an image. At the same time, this code will take care of allowing a UIImageView with an image to be moved around.
Now what happens is this: when moving a selected UIImageView around (for some reason and quite randomly), the image will not stay on top of the other UImageViews in the screen. The reason why I say that this is random is because it will stay on top of some of the other views, but not on top of others.
The behavior is unexpected, several problems arise:
Visually it looks bad; there is no reason why a touched UIImageView should slip under another.
The way I have the code going is to allow UIImageViews to be moved only if they contain an image. So if the UIImageView goes under another who does not contain an image, I cannot touch and move it again. It looks like it is stuck in place.
Please note that I have not been setting subviews at all for this code, thus why this behavior occurs is beyond me.
So what my question boils down to, is there any way that I can tell the code to:
Get the object that was touched.
If it is a UIImageView with an image, then allow me to move the UIImageView.
allow this UIImageView to supersede (be on top of) all other UIImageViews.
Code reference:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{UITouch *touch;
UITouch *touch;
CGPoint touchLocation;
for (UIImageView *fruit in fruitArray)
{
// Check that the UIImageView contains an image
if([fruit image] != nil)
{
// Get the touch event.
touch = [touches anyObject];
// Get the location for the touched object within the view.
touchLocation = [touch locationInView:[self view]];
// Bring the UIImageView touch location to the image's center.
if([touch view] == fruit)
{
fruit.center = touchLocation;
}
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
//allow the selected event (in our case a UIImageView) to be dragged
[self touchesBegan:touches withEvent:event];
}
Thank you for your help! Let me know if you need a better explanation
[self.view bringSubviewToFront:imageView];
This was what you were looking for...

How to detect touch end of image view when touches moving

I have an image view. i detected touch in image view like this
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
int viewTag=[touch view].tag;
if ([[touch view] isKindOfClass:[UIImageView class]])
{
//My code
}
}
and touches moved on image view. whenever my touch moved out off the image view in that particular time i need one alert view. how to detect that touch over from the image view in touches moving?...
I recommend using a UIPanGestureRecognizer and adding it to a larger super-view of the image-view you want to detect on. That way even if the touch starts outside and moves into and out of your image-view you can follow the movement of the touch in your gesture handler.
It's pretty easy, make a method called handlePan: for example, create the gesture recognizer using your handler method, add it to the appropriate super-view. Now whenever the gesture is active and the touch moves your handler method will get called and you can check to see if it is inside your image view.
You should use this method...
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
int viewTag=[touch view].tag;
if ([[touch view] isKindOfClass:[UIImageView class]])
{
//My code
}
else
{
//show the alertView here
}
}
and to check that the initial click was on the imageView you have to set a flag in the touchesBegan method... and check it accordingly in the touchesMoved method
You may add a transparent UIButton of the same size on top of the UIImageViewand track UIControlEventTouchDragOutside
[button addTarget:self action:#selector(draggedOutside:) forControlEvents:UIControlEventTouchDragExit];

iPhone - UIScrollView... detecting the coordinates of a touch [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
UIScrollview getting touch events
Is it possible to detect where in a UIScrollView the finger touched?
I mean, suppose the user uses his finger in this way: taps and scroll, lifts the finger and again, taps and scroll, etc. Is it possible to know the CGPoint where the taps happened in relation to the self.view the scroller is in? The scroller occupies the whole self.view.
Thanks.
You can do it with gesture recognizers. For detect single tap location use UITapGestureRecognizer
UITapGestureRecognizer *tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction:)] autorelease];
[myScrollView addGestureRecognizer:tapRecognizer];
- (void)tapAction:(UITapGestureRecognizer*)sender{
CGPoint tapPoint = [sender locationInView:myScrollView];
CGPoint tapPointInView = [myScrollView convertPoint:tapPoint toView:self.view];
}
To convert that tapPoint to self.view you can use convertPoint:toView: method in UIView class
Take a look at touchesBegan:withEvent: You will get a NSSet of UITouch's, and a UITouch contains a locationInView: method that should return the CGPoint of the touch.
You'd probably be able to subclass it and look at touchesBegan.
http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIResponder_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006783-CH4-SW1
You could find the location in the view and add the scroll ofset to it. Now, your next problem is that -(void)touchesBegan:touches:event won't be called because the events will be sent to your scrollview. This can be fixed by subclassing your UIScrollView and have the scrollview send the touch events to the next responder (your view).
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// Position of touch in view
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
// Scroll view offset
CGPoint offset = scrollView.contentOffset;
// Result
CGPoint scrollViewPoint = CGPointMake(touchPoint.x, touchPoint.y + offset.y);
NSLog(#"Touch position in scroll view: %f %f", scrollViewPoint.x, scrollViewPoint.y);
}

Drag image from one view to another view In iphone/ipad

I am facing below problem:-
Please have a look in the below image the thing what i want is:-
I want to drag default images from view 1 to view 2 and images have to be always thr in view1 so its not like touch moved to draging images .
i tried a lot things in that but i succeed in draging image from one view to another but in view2 i am not able to get touch points so its just adding thr as frame
But i cnt able to touch tht image across view2 and even in view2
i want to do other functionality like zooming and others but first want to get touch points in view2.
I am giving description image about this problem.
The edited question is:-
i have done this simple demo in this i am transferring one view to another view and after getting view2 points its been in its limit boundaries.
but how can i get the default things remain in their.
i will modify this code i will add images in this view. but its just shows my thinking here so guide me here.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
if ([touch view] == view3) {
CGPoint location = [touch locationInView:self.view];
view3.center = location;
return;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
int tmpValue = 0;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
{
onceDone = TRUE;
if(onceDone == TRUE)
{
UITouch *touch = [touches anyObject];
CGPoint pt = [touch locationInView:self.view];
NSLog(#"X = %f y=%f",pt.x,pt.y);
view3.center = pt;
if(view3.frame.origin.x < view2.frame.origin.x )
//view3.frame.origin.x < view2.frame.origin.x)
[view3 setFrame:CGRectMake(159,view3.frame.origin.y, view3.frame.size.width, view3.frame.size.height)];
}
}
[UIView commitAnimations];
}
Please help me.
it is urgent.
Thanks in advance
If you are using pan gestures are touchesMoved method to drag and drop the images.Make super view of view1 and view2 to same UIView and calculate your gesture location or touched point with respect to that common super view.That means your view1 and view2 will be on the same view and each subView(image)is also added to main view only.So you can move images on main view where ever you want and can perform any operation on them.
We have been working in a similar issue, and we have made up with this solution:
We have an UIPanGestureRecognizer added to each button.
When we detect the pan gesture begin, we create the object we want to drag (in this case, it could be a copy of your image). You should have to set a rect equals to the button, or if you create the object in a different view, you should have to convert the object coordinates so the object seems in the same position as the button, but inside his view.
After that we move the last created object, instead of move the button.
And that is, the trick here is the UIPanGestureRecognizer works until you untouch the screen, but it is triggered while you move your finger for all the screen, not only inside the button!
I hope this works for you.

Passing touches through a UIView to a UIScrollView not working

I have a view derived from a UIScrollView controller that I use to page through images in a library. That works fine.
I overlayed a UIView on the right side to handle touches for scrolling quickly through the list of images. My problem is that if I pass the touches through to either 'super' or 'nextResponder' they never make it to the UIScrollView object below.
My question is how can I force the UIScrollView below to handle the touches that I don't need to handle? I'm setting a timer for 0.3 seconds that during that time all touches are passed to the UIScrollView to handle. So if the user started a swipe gesture to turn the page, it will happen.
Here's the code for the touchesBegan method:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
// Start a timer to trigger the display of the slider and the processing of events.
touchesTimer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:#selector(showSlider:) userInfo:nil repeats:NO];
// Where are we at right now?
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
lastPage = [self page:currentPoint.y];
// Pass the event though until we need it.
// [self.nextResponder touchesBegan:touches withEvent:event];
if ([touch.view isKindOfClass:[UIScrollView class]])
{
if (self.nextResponder != nil &&
[self.nextResponder respondsToSelector:#selector(touchesEnded:withEvent:)])
{
[self.nextResponder touchesEnded:touches withEvent:event];
}
}
}
I would try using a regular UIViewController rather than a UIScrollViewController and then add the scroll view object where you need it and put the scroll faster view you want on the right side. This way they are separate and the touches won't get confused.
Here's an easier solutions that worked well for me:
In the UIView on top of the UIScrollview make the width and height both 0 (so that the view is no longer technically on top of the UIScrollView) and set clipsToBounds = NO (so that the contents of the view still show up on top of the UIScrollView).
self.OverlayView.clipsToBounds = NO;
CGRect frame = self.OverlayView.frame;
self.OverlayView.frame = CGRectMake(frame.origin.x, frame.origin.y, 0, 0);
Note that if the UIView contains interactive controls then they will no longer work. You'll need to move it into it's own view above the UIScrollView.