I have a scroll view and a button placed over it , When i add a tap gesture recognizer the button does not work. Is there any way of limiting the tap only to scroll view and not to the button, so that the button functions normally.
here is my code
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesture:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[scroll addGestureRecognizer:tap];
[tap release];
- (void)tapGesture:(UIGestureRecognizer*)gesture{
NSLog(#"scroll tapped");
}
If you do
tap.cancelsTouchesInView = NO;
It will allow button to be pressed. However taps will be detected along with the button press when you press a button. Do avoid this, you will have to subclass UIScrollView and implement the following method –
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
for ( UIView * subview in self.subviews ) {
UIView * hitView = [subview hitTest:point withEvent:event];
if ( hitView )
return hitView;
}
return [super hitTest:point withEvent:event];
}
Implementing the method above pass the touches to the scroll view's subviews.
There is no need to subclass Scrollview. Following code solves the problem easy way. The method gestureRecognizer:shouldReceiveTouch: does the trick.
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesture:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
tap.delegate = self;
tap.cancelsTouchesInView = NO;
[scroll addGestureRecognizer:tap];
[tap release];
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (scroll.superview != nil) {
if ([touch.view isKindOfClass:[UIButton class]])
{
return NO; // ignore the touch
}
}
return YES; // handle the touch
}
- (void)tapGesture:(UIGestureRecognizer*)gesture {
NSLog(#"scroll tapped");
}
Related
I have a View which is the subView of the main view in iphone app I want that when subView is shown and user taps on part of the screen except the subView then subView should hide.
Here is the code which I got but it does not hide it :
UITapGestureRecognizer *tapGR;
tapGR = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)] autorelease];
tapGR.numberOfTapsRequired = 1;
[self.View addGestureRecognizer:tapGR];
// Add a delegate method to handle the tap and do something with it.
-(void)handleTap:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded) {
// handling code
[myViewSheet removeFromSuperView];
}
}
implement UIGestureRecognizerDelegate protocol:
.h:
#interface YourView : UIView<UIGestureRecognizerDelegate>
.m:
#implementation YourView{
UIView * subview;
}
...
subview = [[UIView alloc]initWithFrame:CGRectMake(0, 200, 320, 200)];
[self addSubview:subview];
UITapGestureRecognizer *tapGR;
tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGR.numberOfTapsRequired = 1;
tapGR.delegate = self;
[self addGestureRecognizer:tapGR];
...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view == subView)
{
return NO;
}
else
{
return YES;
}
}
You probably need to set userInteractionEnabled = YES on your main view (The one to which you are attaching the gesture recognizer.)
I have a tutorial for my app, which should display only the first time the app is opened and should be tapped to dismiss.
I am initializing a UITapGestureRecognizer in my viewDidLoad:
tapper_tut = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
tapper_tut.cancelsTouchesInView = FALSE;
[self.view addGestureRecognizer:tapper_tut];
and I have an IBAction to detect the tap and set the tutorial to hidden:
- (IBAction)dismiss_tut{
if (????????????????) {
_tutorial.hidden = YES;
}
}
But I have no idea what to put in the if statement condition, or if this is even that right way to go about this.
How would I dismiss a UIImageView on a tap?
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[self.view addGestureRecognizer:gr];
// if not using ARC, you should [gr release];
// mySensitiveRect coords are in the coordinate system of self.view
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.view];
if (CGRectContainsPoint(mySensitiveRect, p)) {
NSLog(#"got a tap in the region i care about");
} else {
NSLog(#"got a tap, but not where i need it");
}
}
You can make viewDidLoad like this
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
/* Create the Tap Gesture Recognizer */
self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTaps:)];
/* The number of fingers that must be on the screen */
self.tapGestureRecognizer.numberOfTouchesRequired = 1;
/* The total number of taps to be performed before the gesture is recognized */
self.tapGestureRecognizer.numberOfTapsRequired = 1;
/* Add this gesture recognizer to the view */
[self.view addGestureRecognizer:self.tapGestureRecognizer];
}
To detect the taps you can make the method like this.
- (void) handleTaps:(UITapGestureRecognizer*)paramSender
{
NSUInteger touchCounter = 0;
for (touchCounter = 0;touchCounter < paramSender.numberOfTouchesRequired;touchCounter++)
{
CGPoint touchPoint =[paramSender locationOfTouch:touchCounter inView:paramSender.view];
NSLog(#"Touch #%lu: %#",(unsigned long)touchCounter+1, NSStringFromCGPoint(touchPoint));
}
}
you have to declare .h file as "UIGestureRecognizerDelegate"
you have getting tap of gesture as two way as given below steps.
1) Call delegate method of GestureRecognizer (not given action )
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil]; // not given action.
recognizer.numberOfTouchesRequired=1;// here how many tap you want set it
[self.view addGestureRecognizer:recognizer];
recognizer.delegate = self;
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
//whatever you want write code here
return NO;
}
2) given action
UITapGestureRecognizer *oneTouch=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(Addphoto)];
[oneTouch setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:oneTouch];
-(IBAction)Addphoto
{
//whatever you want write code here
}
may be it will help .
I think u need to detect the first time launch of the application which u can do with following
![[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"]
Put this in your if statement .
On parentClass(inheriting from UIView) i have:
[self addGestureRecognizer:_tapGesture]; // _tapGesture is UITapGestureRecognizer, with delegate on parentClass
On someClass:
[_myImageView addGestureRecognizer:_imageViewGestureRecognizer]; // _imageViewGestureRecognizer is UITapGestureRecognizer, with delegate on someClass
The problem is that when i tap on myImageView both gesture recognizers are firing. I want only _imageViewGestureRecognizer to work.
I've tried:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
UIView *gestureView = recognizer.view;
CGPoint point = [touch locationInView:gestureView];
UIView *touchedView = [gestureView hitTest:point withEvent:nil];
if ([touchedView isEqual:_imageViewGestureRecognizer]) {
return NO;
}
return YES;
}
But it ofc doesn't take upon consideration gesture recognizer from super class.
I did this little test and it worked perfectly...
#implementation View
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor whiteColor];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped1)];
[self addGestureRecognizer:tap];
UIImageView* img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"test.png"]];
img.userInteractionEnabled = YES;
img.frame = CGRectMake(0, 0, 100, 100);
[self addSubview:img];
UITapGestureRecognizer* tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped2)];
[img addGestureRecognizer:tap2];
return self;
}
-(void)tapped1 {
NSLog(#"Tapped 1");
}
-(void)tapped2 {
NSLog(#"Tapped 2");
}
#end
What you wanted was iOS's default behaviour. Once a subview has taken care of a touch, its superview won't receive the touch anymore. Did you set userInteractionEnabled on the imageView?
I have a view which contains different textfield.
Clicking on each taxtfield brings up a keyboard and if I click outside the textField the keyboard disappears but the view is also disappear! how can I change the code so that i can only get out of the view using cancel button and tapping down the view not clicking outside of the texfield or by clicking on the background.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
self.view.backgroundColor = [self.appDel.styleManager appBackgroundGradientWithFrame:self.view.bounds];
self.tapView.backgroundColor = [UIColor clearColor];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(endPageEdit:)];
tap.delegate = self;
[self.view addGestureRecognizer:tap];
}
- (void)endPageEdit:(UIGestureRecognizer *)sender
{
if (sender.view == self.view) {
[self.view endEditing:YES];
if ([self isFormVisible]) {
[self handleTap:sender];
}
}
}
In your endPageEdit: method, tell the textFields to resignFirstResponder.
- (void)endPageEdit:(UIGestureRecognizer *)sender {
// assumes you have an outlet set up for each of the textFields
[self.textFieldA resignFirstResponder];
[self.textFieldB resignFirstResponder];
if (sender.view == self.view) {
[self.view endEditing:YES];
if ([self isFormVisible]) {
[self handleTap:sender];
}
}
}
Only zero or one of them will be the first responder, but there's no downside to resigning first responder when the control is not first responder. The reason the view is disappearing must have something to do with the endEditing: method or the handleTap method which you did not post.
How can I detect when the user taps the selection indicator in a UIDatePicker?
Without this the user has to scroll to some other date and then back again to pick the date which is displayed under the selection indicator when the date picker slides up.
Thanks a lot,
Stine
UPDATE: This is the only solution I could come up with myself:
UIDatePicker *aDatePicker = [[UIDatePicker alloc] init];
self.datePicker = aDatePicker;
[aDatePicker release];
[self.datePicker addTarget:self action:#selector(datePicked:) forControlEvents:UIControlEventValueChanged];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(datePicked:)];
[self.datePicker addGestureRecognizer:tap];
[tap release];
Which means that datePicked will be called twice when the user actually rotates the wheel.
UPDATE: The above mentioned solution does not work for UIPickerViews though. I do not know how to achieve the wanted behavior in those cases.
You can do some tweak in this way:-
Conform delegate <UIGestureRecognizerDelegate>in your .h file
UITapGestureRecognizer* gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(pickerViewTapGestureRecognized:)];
[yourDatePicker addGestureRecognizer:gestureRecognizer];
gestureRecognizer.delegate=self;
gestureRecognizer.numberOfTapsRequired=2;//Whenever you do double tap it will called. So allow user to do double tap on selected date.
//Below is the Delegate method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
//Below method will trigger when do the double tap
-(void)pickerViewTapGestureRecognized:(UITapGestureRecognizer*)recognizer
{
UIDatePicker *datePicker=(UIDatePicker*)[[recognizer view] viewWithTag:101];
NSLog(#"datePicker=%#", datePicker.date);
}
Try this code:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(pickerViewTapped:)];
[recognizer setNumberOfTapsRequired:2];
[recognizer setCancelsTouchesInView:NO];
[recognizer setDelaysTouchesEnded:NO];
[recognizer setDelaysTouchesBegan:NO];
[self.answerPicker addGestureRecognizer:recognizer];
// ....
- (IBAction)pickerViewTapped:(UITapGestureRecognizer *)sender {
CGPoint coord = [sender locationInView:self.answerPicker];
if(coord.y <= 126 && coord.y >= 90) {
//do something
}
}
This is an old question but here's what I did in order to grab the selection bar rect on the UIDatePicker. With this, you could just add a button/view with a gesture recognizer to detect taps. It's a bit of a hack but it seems to be working well in iOS6 and iOS7.
+ (CGRect)getSelectionBarRectFromPicker:(UIDatePicker *)picker
{
int counter = 0;
CGRect selectionBarRect;
for(UIView *datePickerView in picker.subviews){
for(UIView *subview in datePickerView.subviews){
if([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0){
if([NSStringFromClass([subview class]) isEqualToString:#"_UIPickerViewSelectionBar"]){
if(counter == 0){
selectionBarRect.origin = subview.frame.origin;
selectionBarRect.size.height = subview.frame.size.height;
}
selectionBarRect.size.width += subview.frame.size.width;
counter++;
}
} else {
if(subview.frame.size.height < 1){
if(counter == 0){
selectionBarRect.origin = subview.frame.origin;
selectionBarRect.size.width = subview.frame.size.width;
} else {
selectionBarRect.size.height = subview.frame.origin.y - selectionBarRect.origin.y;
}
counter++;
}
}
}
}
return selectionBarRect;
}