I have a UIButton whose MultipleTouchEnabled is NO. Still when I drag two fingers across it, the UIEvent I get has 2 UITouches in its allTouches property.
I want to only respond to dragging a finger around my button and ignore the second touch. If I use [[event allTouches] anyObject], I get (obviously) a random touch each time, and instead of a smooth drag across the screen my drag jumps around wildly.
My initial thought is that somehow I am still enabling multitouch, but I find no confirmation for this theory.
Related
I have a simple swipe gesture that I want to be very low priority. I want it to be cancelled by events that happen for controls on the view. At first, I thought this would be simple. It's easy to cancel events when a gesture happens, but I can't seem to do the opposite.
My solution is to cancel the gesture if it conflicts with any thing that is touchable. Here is the code I hacked together:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint touch = [gestureRecognizer locationInView:self.view];
return [self.view hitTest:touch withEvent:nil] == self.view;
}
I feel this is the wrong solution to the problem. What am I missing? What is the right way to get events to cancel gestures?
For more context, I have two UISwipeGestureRecognizers (swipe left and swipe right) added to the view. There is also a UISlider in the view (part of an embedded MPVolumeView). When I moved the slider to change the volume, the left or right swipe would fire.
This is the correct way to do what you want. You are telling the gesture recognizer that it should only begin if the touch is directly in the view, not any subviews (according to hitTest: which is good because it allows the views to decide if they are hit or not).
It's always better to prevent it from starting rather than trying to cancel it afterwards. However, if you do want to cancel the gesture after it has started, set enabled = NO and then back to YES again.
If you need to allow the gesture for some subviews but not controls you can test if the view returned by hitTest: is a subclass of UIControl (for example) using isKindOfClass:.
I don't know what type of gesture this is for, but usually you don't need to do this because UIKit will automatically find the deepest view that wants the touches and that view will 'eat' them so outer gesture recognizers won't get them - however I can imagine this doesn't hold true for some combinations of recognizer/control.
I can't find anywhere in the documentation. When this message is called on my subclass of UIView:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
How can I get the touch for which this message was called ?
On both the NSSet and UIEvent I can get only sets of touches, but no unique identifier so I can determine which touch triggered the message.
PS: why on hell would they send a NSSet of all touches, and also the possibility to get the same set from [[event allTouches] anyObject]
You can't get the touch, because sometimes multiple touches triggered the message. If the user has two fingers on the screen, and moves both, you can get a single touchesMoved:withEvent: in which both touches are updated.
You need to process every touch in the touches set. If you've disabled multitouch for the view, so that you know there will only ever be one touch in the set, you can use touches.anyObject to get the touch. But if you haven't disabled multitouch, you need to loop over all of the touches in the set.
The message includes a set of touches separate from event.allTouches because the user might have three fingers down but only move one or two of them. The touches set only contains the moved touches, but event.allTouches contains all of the user's touches, including the touches that have not moved since the last message.
The unique identifier for the touch is the UITouch object itself. When the user puts a finger on the screen, iOS creates a UITouch object. It updates that object as the user moves his finger. So you can use the UITouch object as the key in an NSDictionary, or you can attach your own objects to it using objc_setAssociatedObject.
Im pretty new to i-phone development and I am trying to program a basic bubble popper. I have been able to program a game that creates a 10X10 grid using an NSMutableArray and allows you to touch and object and "pop" it. When I went to use a sprite atlas instead of just a UIImage (animated graphics are much more exciting) it changed the the y coordinate of 0 to the bottom left side of the screen when before I believe 0,0 started at the top left side of the screen. So now my touch will have the y inverted so when I touch the 0,0 element it will activate the 0,9 element and my 0,1 will activate the 0,8 element and so on. I have been searching for a while to find out what I might be doing wrong or if there is a beter solution to programing a touch detecting function for what seems to be a simple enough game. Any Ideas?
two things:
please provide source code because it makes you issue easier to understand
have you look at game programming libraries (http://cocos2d.org/ for example) ?
Assuming you are handling the touch from within CCLayer's ccTouchesBegan:withEvent: method:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [self convertTouchToNodeSpace:touch];
// now the location CGPoint variable contain coordinate of the touch aligned to the cocos2d coordinate system
[self popBubbleAtLocation:location];
}
Is it possible to control when the UITableView scrolls in my own code.
I am trying to get behaviour where a vertical swipe scrolls and a horizontal swipe gets passed through to my code (of which there are many example)
BUT
I want a DIAGONAL swipe to do nothing, i.e the UITableView should not even begin scrolling.
I tried catching it in here
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
but the scrollView.contentOffset.x is always 0 so I cannot detect a horizontal movement.
I also tried subclassing UITableView and implementing
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
etc..
but the UITableView (and I guess it's parent UIScrollView) start to scroll before the touches are notified?
To re-iterate, I want the UITableView scrolling to be locked if a diagonal swipe is made, but to scroll vertically normally.
(This behaviour can be seen in Tweetie(Twitter) for the iPhone)
Thanks for any help!
If you can work with 3.2 or later, the UIGestureRecognizer suite should allow this. There are a series of calls allowing some gestures to cancel or interoperate with other gestures, and you should be able to create a custom diagonal swipe gesture that cancels other gestures but does not actually do anything itself.
Prior to 3.2 the UIScrollView gesture handling is essentially undocumented. You can detect taps but not movements through the standard touchesBegan UIResponder calls. I think that once it detects movement it commandeers the run loop and captures all events, bypassing the normal event chain.
Note that setContentOffset is always called. You can create a subclass of UIScrollView and when you detect a diagonal shift during event tracking do not pass it to super. I do not know if, or how well this would work but it is somewhere to start.
I am going to develop a ball game where i have to touch two/more
ball simultaneously.So how will i detect these multiple touch.
I came to know the following way i can detect multiple touch-
-(void)touchesBegan:(NSSet*)toucheswithEvent:(UIEvent*)event
{
UITouch* touch = [touches anyObject];
NSSet *touch2 = [event allTouches];
[touch2 count] //which count no. of touches
}
which detect only no. of touch. But I need to find out the (x-co-ordinate,y-co-ordinate) of these touch point.Not only this when i throw (means touch inside a ball and then slide the cursor) these ball how will i identify which ball is moving(means touchmove will identify which touchbegan??and if for each ball touchmove is called then how will i reset ball position because i gettting two touchposition(x1.x2) and (x2,y2) for 2 ball,so how will i say which ball belongs to (x1,y2) or (x2,y2)) .
In your code about touch2 is a set of UITouch objects
You can get at each object like so:
UITouch *touch = [[touch2 allObjects] objectAtIndex:0];
EDIT: to add information about touchesMoved
touchesBegan is called when one or more fingers is placed on the screen.
At this point you will need to determine which ball corresponds to each touch (by using the coordinates of each touch). You will need to store this mapping.
touchesMoved will be called continually as the fingers are moved across the screen. Using the mapping you calculated earlier, you can determine which ball corresponds to which UITouch and apply some movement to it as you see fit.
Perhaps you should read handling a complex multi-touch sequence in the apple docs.