Detect touches on a UIView inside UIScrollView preferably with Interaction disabled - objective-c

I have a UIScrollView with some UIViews in it.
What I am trying to do, is catch the touches events when the UIViews are touched/untouched.
The problem I am having, is the UIScrollView seems to swallow all the touch events, especially if you hold for too long on a UIView.
I preferably want the UIScrollView to have userInteraction disabled as it scrolls automatically.
Is this possible?
I have tried subclassing the UIViews but the touches events are never called in it.

You can attach a tapGesture to your scrollview with something along those lines:
UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureUpdated:)];
tapGesture.delegate = self;
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[self addGestureRecognizer:_tapGesture];
then in your - (void)tapGestureUpdated:(UITapGestureRecognizer *)tapGesture method this is your responsability to determine the location of the touch and find out if there was a picking on one of your subviews. You could call then a method on a delegate that notify that a specific view has been touched.

Perhaps reordering your views so that a view that has a touch recognizer object associated with it is what the app recognizes. Move it in the document outline to the top (scroll view)

Related

How to detect a tap gesture in subviews

Quick question: how do i detect if a tap gesture recognizer is within a subview of the view it is added to? Eg. if i click on an object such as a square that has been added as a subview to a background which a tap gesture recognizer has been added to, how do I detect that it has been tapped?
You can grab the point of the tap off the gesture recognizer when your handler method is called respective to any view you wish using -locationInView:. Then, use the following method on UIView: - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event to get a reference to the actual sub view that was tapped remembering that the point you pass in is in the same coordinate space as the view.
Some code to get you started:
CGPoint point = [tapGestureRecognizer locationInView:parentView];
UIView *tappedView = [parentView hitTest:point withEvent:nil];
For hit testing to work the view needs to have the userInteractionEnabled property set to YES. Many views, such as UILabels have this set to NO by default. So prior to the above:
self.subviewOfInterest.userInteractionEnabled = YES;
maybe you should set as:
subviews.userInteractionEnabled = YES;
good luck!
you can use the requireGestureRecognizerToFail: to recognize the tap on subview please refer this code

Trouble with gesture recognizers in subviews

I'm having a rather basic problem, I've looked around (here, google, etc) and haven't found a solution for this:
In my View Controller's viewDidLoad, I have this:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(myfunc:)];
//I have a UIScrollView named "containerView"
//here's some code that creates an UIView in a variable named "myView"
//this works fine, I can see "myView" when I run it
[containerView addSubview:myView];
[myView addGestureRecognizer:longPress];
and then I have this function in the same class:
- (void)myfunc:(UIRotationGestureRecognizer *)recognizer
{
NSLog(#"hola!"); //never runs
}
The call to NSLog never runs. What am I doing wrong?
EDIT
Some extra info: it seems no touch events are ever sent to the subview. However, I tried adding an UIView with a button inside, all in the UIScrollView, and the button receives the touch event just fine, so the problem is only with programmatically added subviews.
Strangely enough, adding a "container" UIView inside the UIScrollView, and then the other subviews inside this container, made it work. Now touch events are sent to the subviews.
How can a superview interecept a touch sequence before any of its subviews?
TLDR:
[containerView setCanCancelContentTouches:NO];
do it just as you add the gesture recogniser to the scroll view.
also look into
[containerView setDelaysContentTouches:NO];
If the above behaviour isn't quite right.
for more info:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html
I think on myFunc you must do somethings like that:
switch (reconiger.state)
{
case UIGestureRecognizerBegin:
//Do something when start recognizer
break;
case UIGestureRecognizerEnd:
//Do something when end recognizer
break;
}

How do I make the keyboard go away when a user clicks on the background of the view?

I have a UITextField in my iOS app. When a user enters text and clicks Return, the keyboard goes away due to a call to an IBAction with "resignFirstResponder."
However, XCode does not let me drag a line from the UIView itself to File Owner. How do I associate touching the background of a UIView with an IBAction that makes the keyboard go away?
You can use UITapGestureRecognizer. see: Dismiss keyboard by touching background of UITableView
so instead of tableview, just add it to your view instead:
UITapGestureRecognizer *gestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)] autorelease];
gestureRecognizer.cancelsTouchesInView = NO; //so that action such as clear text field button can be pressed
[self.view addGestureRecognizer:gestureRecognizer];
and have a method to hide your keyboard
- (void) hideKeyboard {
[self.view endEditing:YES];
}
You've already noticed that you can't drag from the UIView to the file's owner to assoctiate an action with a touch.
The way to work around this is to change the class of the background view from UIView to UIControl and hook up an action from there to a method in your controller to stop editing.
That's because a UIControl can respond to touch events, and a UIView does not, but a UIControl subclasses UIView, and so it can be used in place of a UIView.
I wrote an example project a while ago that uses this technique. Have a look at the secondViewController's xib file and see how I've change the class of the background view and hooked it up to a an action in the controller to dismiss the keyboard.
Use the touchesBegan with Event and end editing on the view:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
One easy way to do it is to create a big transparent UIButton behind the view.

NSView mouse tracking

I'm facing a strange behavior with Cocoa NSView on Mac OS X.
I've a custom NSView in a NSView container, this custom NSView tracks mouse movements, clicks, and has a tooltip.
When I add a NSView above the described view, I can still see the tooltips even if the view with the tooltip is under, behind and not visible.
I'm pretty sure that I misunderstood something in the event handling chain. Any help is really appreciated!
The core issue is that you are not supposed to have overlapping views in Cocoa. Or at least, the behavior then becomes undefined. A view can be a subview of another view, but not simply a sibling within the bounds of the other view.
However, one way to solve your particular problem is to make the view underneath hidden, using the setHidden: method.
If you're not using it anymore you can call the removeFromSuperview method.
NSView *myView
[myView alloc] init]
// do stuff
[myView removeFromSuperview]
if you just don't want it to receive events you can call the resignFirstResponder method
NSView *myView
[[myView alloc] init]
// do stuff
[myView resignFirstResponder]

how to detect number of touches on the uiview in iphone sdk

in my app, when the user touches on the view ,i am showing an UIImageView there and i drag and
drop the image from another UIImageView to that touched UIImageView.
But the problem is that, only the recent touched UIImageView is activated. i mean ,when i
click 3 times then shows 3 UIImageViews but only the last is activated and accept the another
image.
How can i make all touched UIImageViews are activated .. Any body help on this..
Thanks in advance.
You should read Apples documentation on the responder chain and event handling. The key UIView method here is
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
This method traverses the view hierarchy by sending the
pointInside:withEvent: message to each subview to determine which
subview should receive a touch event. If pointInside:withEvent:
returns YES, then the subview’s hierarchy is traversed; otherwise, its
branch of the view hierarchy is ignored. You rarely need to call this
method yourself, but you might override it to hide touch events from
subviews.
You should try this:
Where there is your UIView (Or a view):
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapped:)];
tapGesture.numberOfTapsRequired = 1;//number of tap
[view addGestureRecognizer:tapGesture];
The selector:
-(void)tapped:(UITapGestureRecognizer *)sender {
NSLog(#"Pressed");
}