UIBarButtonItem and UIGestureRecognizer - objective-c

I have a UIView where i added a UITapGestureRecognizer:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
tapRecognizer.numberOfTapsRequired=1;
tapRecognizer.numberOfTouchesRequired=1;
[self.myView addGestureRecognizer:tapRecognizer];
I then add a UIToolBar with a button to the view:
UIToolbar *topBar = [[UIToolbar alloc ]initWithFrame:CGRectMake(0, 0, self.myView.frame.size.width, 44)];
topBar.barStyle = UIBarStyleBlackTranslucent;
UIBarButtonItem *logout = [[UIBarButtonItem alloc] initWithTitle:#"Logout" style:UIBarButtonItemStyleBordered target:self action:#selector(logout)];
[topBar setItems:#[logout] animated:NO];
I'm having an issue where I click on the logout button, and my tap recognier fires instead of my logout action. If I click and hold, then the logout action will fire (I'm guessing the tap recognizer is failing so lets the buttion action fire).
how can I not fire the gesture recognizer when the button is pressed?

Just had the same problem. Because I don't want to introduce container views (the UIToolbar should cover my existing view). With the help of Patrick.Ji's coarsely pointing I came up with this:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view.superview isKindOfClass:[UIToolbar class]]) {
return NO;
}
return YES;
}
Don't forget to set the delegate of the gesture to self
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *mainTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(mainTapGesture:)];
mainTapGestureRecognizer.delegate = self;
[self.view addGestureRecognizer:mainTapGestureRecognizer];
}

Check the view in your tap recognizer. If it is your logout button, let the touch fail to pass it up the chain via super.
Alternatively, make sure your toolbar is not a subview of your view. Instead, have a container view containing with your toolbar and your content view, and add the gesture recognizer to this content view.

implement this delegate method of UIGestureRecognizer (remember to set your tapRecognizer.delegate = self)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch: (UITouch *)touch {
if ([touch.view isKindOfClass:[UIBarButtonItem class]])
{
return NO;
}
return YES;
}

Related

How to load new view in the same window on button click?

I've got the View-Controller with a button. I want the new view to be loaded over my View-Controller when the button is pressed. It'd not replace the existing view, I want it to be smaller than the screen and hide when I tap out of the small view.
How should it be implemented in code?
- (IBAction)button:(id)sender
{
UIView *view2=[[UIView alloc]initWithFrame:CGRectMake(0,0,200,200)];
[self.view addSubview:view2];
UITapGestureRecognizer *Tap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(Tapview)] autorelease];
[view2 addGestureRecognizer:Tap];
}
-(void)Tapview
{
[view2 removeFromSuperview];
}
Add Tap Gesture to self.view like this:
UITapGestureRecognizer *oneFinger =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerAction:)] autorelease];
// Set required taps and number of touches
[oneFinger setNumberOfTapsRequired:1];
[oneFinger setNumberOfTouchesRequired:1];
// Add the gesture to the view
[[self view] addGestureRecognizer:oneFinger];
Add one BOOL flag in .h file; in ViewDidLoad method add this:
flag = FALSE;
Now I assume u have UIView *smallView which be added on screen like this:
[self.view addSubView:smallView];
flag = TRUE;
smallView.center = self.view.centre;
Now when tapped on self.view tap gesture action called
- (void)oneFingerAction:(UITapGestureRecognizer*)sender
{
if(sender.view == self.view)
{
if(flag){
if(smallView)
{
[smallView removeFromSuperView];
}
}
}
}

Tap Recognition for UIImageView in the UITableViewCell

Currently I'm facing a problem, I would like to perform action when the UIImageView on my UITableViewCell had been tapped.
Question: How could I do it? Could any one show me the code, or any tutorial?
Thanks in advance!
This is actually easier than you would think. You just need to make sure that you enable user interaction on the imageView, and you can add a tap gesture to it. This should be done when the cell is instantiated to avoid having multiple tap gestures added to the same image view. For example:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myTapMethod:)];
[self.imageView addGestureRecognizer:tap];
[self.imageView setUserInteractionEnabled:YES];
}
return self;
}
- (void)myTapMethod:(UITapGestureRecognizer *)tapGesture
{
UIImageView *imageView = (UIImageView *)tapGesture.view;
NSLog(#"%#", imageView);
}
Try this
//within cellForRowAtIndexPath (where customer table cell with imageview is created and reused)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
[imageView addGestureRecognizer:tap];
// handle method
- (void) handleImageTap:(UIGestureRecognizer *)gestureRecognizer
{
RKLogDebug(#"imaged tab");
}
make sure u have....
imageView.userInteractionEnabled = YES;
you can use a customButton instead UIImageView
A tap gesture recogniser can be very memory hungry and can cause other things on the page to break. I would personally reconmend you create a custom table cell, insert a button into the custom cell frame and in the tableview code set the self.customtablecell.background.image to the image you want. This way you can assign the button an IBaction to make it push to whatever view you want.
Use ALActionBlocks to action in block
__weak ALViewController *wSelf = self;
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithBlock:^(UITapGestureRecognizer *weakGR) {
NSLog(#"pan %#", NSStringFromCGPoint([weakGR locationInView:wSelf.view]));
}];
[self.imageView addGestureRecognizer:gr];

multitouch and buttons in same view

hi I have an app UIViewController that supports multitouch and has some buttons too, what i need is that when user double click on button it opens a new view, and when the user move is finger on screen it opens other view.
The app works fine if user put his finger in the area where there is no button, but if he puts his fingers in the area where there are buttons nothing happens
- (void)viewDidLoad
{
[super viewDidLoad];
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(openPic:)
forControlEvents:UIControlEventTouchDownRepeat];
button.tag = image;
button.frame = CGRectMake(orInc, inc, 70.0, 95.0);
[self.view addSubview:button];
]
-(void) openPic:(id)sender {
UINavigationController *nav=[[UINavigationController alloc]init];
PicController *x=[[PicController alloc]init];
nav.viewControllers=[NSArray arrayWithObject:x];
[self.navigationController pushViewController:x animated:YES];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UINavigationController *nav=[[UINavigationController alloc]init];
ViewController *x=[[ViewController alloc]init];
nav.viewControllers=[NSArray arrayWithObject:x];
[self.navigationController pushViewController:x animated:YES];
}
Set userInteractionEnabled property of he UIButton object to NO and try it.

Delimit UISwipeGestureRecognizer

there is a way to delimit the swipe only on a specific item?
in this way it works everywhere
UIGestureRecognizer *recognizer;
//RIGHT
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
self.swipeRightRecognizer =(UISwipeGestureRecognizer *)recognizer;
swipeRightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRightRecognizer];
self.swipeRightRecognizer = (UISwipeGestureRecognizer *)recognizer;
[recognizer release];
thanks!
You can add the swipe recognizer to only the view you want to swipe. Or, you can do this:
swipeRightRecognizer.delegate = self;
//...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
return (touch.view == myViewThatShouldReceiveSwipes);
}

Disable gesture recognizer

I have two types of recognizer, one for tap and one for swipe
UIGestureRecognizer *recognizer;
//TAP
recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(numTap1:)];
[(UITapGestureRecognizer *)recognizer setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:recognizer];
self.tapRecognizer = (UITapGestureRecognizer *)recognizer;
recognizer.delegate = self;
[recognizer release];
//SWIPE RIGHT
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
self.swipeRightRecognizer =(UISwipeGestureRecognizer *)recognizer;
swipeRightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRightRecognizer];
self.swipeRightRecognizer = (UISwipeGestureRecognizer *)recognizer;
[recognizer release];
with this function I can disable taps on some objects.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ((touch.view == loseView) || (touch.view == subBgView) || (touch.view == btnAgain)) {
return NO;
}
return YES;
}
How can I disable swipes?
Thanks a lot!
UIGestureRecognizer has a property named enabled. This should be good enough to disable your swipes:
swipeGestureRecognizer.enabled = NO;
Edit: For Swift 5
swipeGestureRecognizer.isEnabled = false
Why don't you set the delegate for the swipe gesture recognizer too and handle them within the same delegate method.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ( [gestureRecognizer isMemberOfClass:[UITapGestureRecognizer class]] ) {
// Return NO for views that don't support Taps
} else if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] ) {
// Return NO for views that don't support Swipes
}
return YES;
}
I have a similar issue. Some of my disabled users tap and swipe at the same time, so the app moves to the next screen. I set up an option to allow them to use a three-fingered tap instead. I need to invoke the option the popoverControllerDidDismissPopover delegate and when the app first starts. So I wrote a method that combines the answers above. It looks for all of the swipe gesture recognizers and turns them off, then turns on my tap gesture recognizer.
- (void)changeGestureRecognizer {
// Three finger tap to move to next screen
if ([Globals sharedInstance].useDoubleTapToMoveToNextScreen) {
// Let’s see which gestures are active and turn off the swipes
for (UIGestureRecognizer *gestureRecognizer in self.view.gestureRecognizers) {
NSLog(#"The gestureRecognizer is %#", gestureRecognizer);
if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] ) gestureRecognizer.enabled = NO;
}
// Add the three finger tap
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeNext)];
[twoFingerTap setNumberOfTapsRequired:1];
[twoFingerTap setNumberOfTouchesRequired:3];
[self.view addGestureRecognizer:twoFingerTap];
}
}