how to get touch event after a button click in iphone? - iphone

I have a UIButton in my project and after a button click I am showing a UIView on the top of that button in such a way that the button remains hidden that time. I want to get a touchesmoved event on that time when I keep that button pressed and move finger over the overlapped UIView. As far as I did is like the following:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
if ([touch view] == uiview)
{
NSLog(#"Touches moved");
}
but it doesnt get called when I keep the button pressed that is hidden when the UIView comes up and the uiview goes hidden when I release the button. Any suggestion please?

I don't quiet understand what your trying to do but I would suggest you use UIGestureRecognizers and add Gestures Recognizers to your button.
Try using this code. I've used this in a card game i developed. moving cards around using long press gestures. Hope i helps.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(addLongpressGesture:)];
[longPress setDelegate:self];
[YOUR_BUTTON addGestureRecognizer:longPress];
- (void)addLongpressGesture:(UILongPressGestureRecognizer *)sender {
UIView *view = sender.view;
CGPoint point = [sender locationInView:view.superview];
if (sender.state == UIGestureRecognizerStateBegan){
// GESTURE STATE BEGAN
}
else if (sender.state == UIGestureRecognizerStateChanged){
//GESTURE STATE CHANGED/ MOVED
CGPoint center = view.center;
center.x += point.x - _priorPoint.x;
center.y += point.y - _priorPoint.y;
view.center = center;
// This is how i drag my views
}
else if (sender.state == UIGestureRecognizerStateEnded){
//GESTURE ENDED
}

You need to set view.userInteractionEnabled = NO for your overlapped UIView.
This will send action to button.

Related

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];

How can you switch from using one UIButton to another while still holding down finger?

Imagine your keyboard. Imagine yourself placing one finger down one key, then (while holding down) moving your finger all the way across to another key on the keyboard. Now, imagine that each key on the keyboard is a UIButton. when you are holding your finger on the current key, this key (UIButton) is highlighted. Then, when the user moves across to another key, the first key is no longer highlighted, and the current key that is pressed down, is highlighted.
Now, I have a 6 x 8 grid of UIButtons each 53 x 53 pixels. So, I have 48 UIButtons. I want to replicate this kind of idea. The button that the users finger is upon, will have a image that is slightly lighter (to look selected like), and all others will will not be slightly lighter.
Here is my idea of how to go about this,
1) Create all 48 UIButtons in viewDidLoad. Add the lighter image to UIControlStateHighlighted for all UIButtons.
2) Add some sort of target for touchUpOutside that somehow makes the current button not highlighted and not usable. (maybe set the highlighted and userInteractionEnabled to no). But then how can I tell the next button to be used? And how can I say that I want the specific UIButton that the users fingers are under to become highlighted and in use to detect gestures and stuff.
Also, this touchUpOutside method may not work because all the buttons are right next to each other, and I think you have to drag far out to run this touchUpOutside.
It's also important to note that the buttons are not placed in equal rows and columns. Sometimes one button will actually be a UIImage but look like a UIButton. So, doing some sort of fast enumeration comparing frames for some reason will not work.
Two observations:
I generally use gesture recognizers for stuff like this, not the various touchUp... methods.
I know you said you don't want a fast enumeration through the subviews, but why not? Just because some are different classes than others is not a problem (because you could just test the isKindOfClass method). (And, as an aside, I'm not sure why some would be buttons and some would not.) Just because they don't line up really makes no difference, either.
Anyway, for stuff like this, I frequently will put the gesture recognizer on the shared parent view (e.g. typically the view controller's view), and then enumerate through the subviews to see in which the current CGPoint is contained?
CGPoint location = [sender locationInView:self.view];
for (UIView *subview in self.view.subviews)
{
if (CGRectContainsPoint(subview.frame, location))
{
// do your appropriate highlighting
if ([subview isKindOfClass:[UIButton class]])
{
// something for buttons
}
else if ([subview isKindOfClass:[UIImageView class]])
{
// something for imageviews
}
return;
}
}
I don't know if any of this makes sense to you, but it seems easiest to me. If you clarify your intent, perhaps I can refine my answer further.
Just as a practical example, you could define a continuous gesture recognizer that kept track of the first and last subview that was clicked on (and if you don't start your gesture on a subview, no gesture is generated, and if you don't stop your gesture on a subview, it cancels the whole thing), e.g.:
#interface SubviewGestureRecognizer : UIGestureRecognizer
#property (nonatomic,strong) UIView *firstSubview;
#property (nonatomic,strong) UIView *currentSubview;
#end
#implementation SubviewGestureRecognizer
- (id) initWithTarget:(id)target action:(SEL)action
{
self = [super initWithTarget:target action:action];
if (self)
{
self.firstSubview = nil;
self.currentSubview = nil;
}
return self;
}
// you might want to tweak this `identifySubview` to only look
// for buttons and imageviews, or items with nonzero tag properties,
// or recursively navigate if it encounters container UIViews
// or whatever suits your app
- (UIView *)identifySubview:(NSSet *)touches
{
CGPoint location = [[touches anyObject] locationInView:self.view];
for (UIView *subview in self.view.subviews)
{
if (CGRectContainsPoint(subview.frame, location))
{
return subview;
}
}
return nil;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if ([touches count] != 1)
{
self.state = UIGestureRecognizerStateFailed;
return;
}
self.firstSubview = [self identifySubview:touches];
self.currentSubview = self.firstSubview;
if (self.firstSubview == nil)
self.state = UIGestureRecognizerStateFailed;
else
self.state = UIGestureRecognizerStateBegan;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
self.currentSubview = [self identifySubview:touches];
self.state = UIGestureRecognizerStateChanged;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
self.currentSubview = [self identifySubview:touches];
if (self.currentSubview != nil)
self.state = UIGestureRecognizerStateEnded;
else
self.state = UIGestureRecognizerStateFailed;
}
- (void)reset
{
[super reset];
self.firstSubview = nil;
self.currentSubview = nil;
}
You could then set this up in viewDidLoad:
SubviewGestureRecognizer *recognizer = [[SubviewGestureRecognizer alloc] initWithTarget:self action:#selector(handleTouches:)];
[self.view addGestureRecognizer:recognizer];
And then define your handler as such (this works with buttons and image views, taking advantage of the fact that both support setHighlighted):
- (void)handleTouches:(SubviewGestureRecognizer *)sender
{
static UIControl *previousControl = nil;
if (sender.state == UIGestureRecognizerStateBegan || sender.state == UIGestureRecognizerStateChanged)
{
if (sender.state == UIGestureRecognizerStateBegan)
previousControl = nil;
UIView *subview = sender.currentSubview;
if (previousControl != subview)
{
// reset the old one (if any)
[previousControl setHighlighted:NO];
// highlight the new one
previousControl = (UIControl *)subview;
[previousControl setHighlighted:YES];
}
}
else if (sender.state == UIGestureRecognizerStateEnded)
{
if (previousControl)
{
[previousControl setHighlighted:NO];
NSLog(#"successfully touchdown on %# and touchup on %#", sender.firstSubview, sender.currentSubview);
}
}
else if (sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed)
{
[previousControl setHighlighted:NO];
NSLog(#"cancelled/failed gesture");
}
}
Here is a fairly simple way to do this. Assuming you are creating your buttons programmatically (it would be a huge pain to do this with interface builder). This method works in subclasses of UIViewController, UIView, and UIGestureRecognizer.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//get the touch object
UITouch *myTouch = [touches anyObject];
//get the location of the touch
CGPoint *myPoint = [myTouch locationInView:self.view];
//detect if the touch is in one of your buttons
if ( CGRectContainsPoint(myButton.frame, myPoint){
/*do whatever needs to be done when the button is pressed
repeat the CGRectContainsPoint for all buttons,
perhaps using a while or for loop to look through an array?*/
}
}
This method only detects when the user puts their finger down, you will need to use these methods to detect other movements:
touchesMoved:withEvent detects when the finger moves across the screen without lifting up
touchesEnded:withEvent detects when the finger is lifted off the screen
touchesCancelled:withEvent: detects when something interrupts the app, like receiving a call or locking the screen

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);
}

uiimageview touches problem

i am developing a card game which requires uiimageviews. i have a view based application. i have added 5imageviews in it.
each imageview has a unique card. nw the user can drag a card on top of any other card present. for this i need to know which card has been selected. how to do this?
touches enabled works in all places in my view. i want touches to be enabled only on uiimageview.
how can i activate touches to the imageviews alone present in my viewcontroller.
thanks in advance..
What you can do is in touchesBegan: method you can check which location in your view is selected using
CGPoint point = [recognizer locationInView:self];
And then do a for loop to check which imageview is selected like this
for(i = 0; i < 5; i++)
{
if(CGRectContainsPoint(imageView.frame, point))
{
// do something.
}
}
UITouch *touch = [touches anyObject];
CGPoint offSetPoint = [touch locationInView:myImageView];
Now u have defined only the myImageView object to receive the touches. Write these lines the touchesBegan or touchesEnded method as u require... Hope this helps....Dont forget to set the userInteractionEnabled property of the imageview to YES for the touches to work.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint pnt = [[touches anyObject]locationInView:self.view];
UIImageView *imgView;
if((pnt.x > CGRectGetMinX(imgView.frame) && pnt.x < CGRectGetMaxX(imgView.frame))&&
(pnt.y > CGRectGetMinY(imgView.frame) && pnt.y < CGRectGetMaxY(imgView.frame)) &&
ChkOfferCount==TRUE)
{
UIAlertView *obj = [[UIAlertView alloc]initWithTitle:#"Image Touched"
message:#"Selected image is this" delegate:nil
cancelButtonTitle:#"cancel"
otherButtonTitles:#"ok",nil];
[obj show];
[obj release];
}
}
Set imageView.userInteractionEnabled=YES; and you can work with the touches methods on the imageView itself e.g. touchesBegan: You can work with these methods to handle the drag and drop of the cards.
You can also create UIControl view then fill it entirely with UIImageView then simply catch touch events in UIControl.

TouchesMoved with Button?

Is it possible to use the touchesMoved function with buttons instead of UIImageViews?
Yes.
In your .h file
IBOutlet UIButton *aButton;
In your .m file
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event touchesForView:self.view] anyObject];
CGPoint location = [touch locationInView:touch.view];
if(CGRectContainsPoint(p1.frame, location))
{
if (!p1.isHighlighted){
[self pP01];
[p1 setHighlighted:YES];
}
}else {
[p1 setHighlighted:NO];
}
//
if(CGRectContainsPoint(p2.frame, location))
{
if (!p2.isHighlighted){
[self pP02];
[p2 setHighlighted:YES];
}
}else {
[p2 setHighlighted:NO];
}
if(CGRectContainsPoint(p3.frame, location))
{
if (!p3.isHighlighted){
[self pP03];
[p3 setHighlighted:YES];
}
}else {
[p3 setHighlighted:NO];
}
}
And finally, in Interface Builder, connect your button to 'aButton' and turn off "User Interaction Enabled" for your button.
This is important because it allow touchesMoved to handle it.
I have adjusted the code above to check the buttons highlighted state. This is to stop it from firing the button multiple times when you drag your finger inside the area.
To get your "piano keys" to work when you tap them, use -(void)touchesBegan
To set your button highlight states back to = NO;, use -(void)touchesEnded
I have had to find out the exact same thing you are after. I couldn't figure out Touch Drag Enter
So to avoid multiple posts on the subject, please check out my question and answers.
question 1
question 2
You could certainly find the 'view' that is currently being touch event is dragging over even if it is a button. You could also use the 'touch drag enter' connection for buttons in the Interface Builder. Look at the connections tab by pressing cmd+2 when having selected a button.