I've hidden the navigation bar and the status bar, now the screen edge pan gesture to go back won't work, is this typical? - ios

I'm curious, if I set the navigationBar to hidden, and also hide the status bar, my view controller no longer responds to the screen edge gesture to pop the view controller.
Is this expected behaviour? I tried to set the interactivePopGestureRecognizer to enabled in viewDidLoad after I hide the navigation bar, but it still won't work.

[self.navigationController.navigationBar setHidden:YES];<--doesn't remove pop gesture
[self.navigationController setNavigationBarHidden:YES];<-- disables pop gesture
Simply use the first option, and in your root controller's viewDidAppear method use:
[self.navigationController.navigationBar setHidden:NO];

Are you sure you've done things right? I've put together an example that seems to work for me. All I did was make the navigationController.navigationBar.hidden = YES and [[UIApplication sharedApplication] setStatusBarHidden:YES]
-edit-
After closer inspection, it looks like there are two different properties on UINavigationController. There is navigationBar which is the UINavigationBar view, and there is navigationBarHidden which is a boolean. When you set navigationBarHidden to true, the swipe gesture stops working. But if you set that actual view to be hidden with navigationBar.hidden then the gesture still works. Check the Git repository for an example.

A very simple work around:
Link a swipe gesture method to your navigation back button. Make the current view controller the target of the gesture recognizer (self), with the selector popThisViewController. Then install the gesture recognizer into the view that the user will swipe on. Don't forget to add your go back action
edit added swipe gesture for reference to other coders that don't know
Cleaner code will look like this:
UISwipeGestureRecognizer *gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(goBack:)];
gesture.numberOfTouchesRequired = 1;
gesture.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRight];
}
-(IBAction)goBack:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}

Related

How to prevent double action from simultaneous button touches on UINavigation bar?

In a UINavigation bar, there is a right custom share UIBarButtonItem and a back button in the left UIBarButtonItem. When simultaneously tapping on both buttons, the app produces a black view, possibly because both buttons are attempting to display a new view simultaneously - the share button presents a UIActivityViewController and the back button a VC from the prior screen.
In looking through similar questions here, I've tried the following solutions but neither prevented a black view from appearing on a simultaneous button touch:
Inserting exclusiveTouch into ViewDidLoad in the following 2 ways
a)
for(UIView *temp in self.navigationController.navigationBar.subviews)
{ [temp setExclusiveTouch:YES]; }
b) [self.navigationController.navigationBar setExclusiveTouch:YES];
Applying self.navigationController.navigationBar.userInteractionEnabled = NO; after a touch.
Are there other solutions?
Is this related to multi-threading?
In each touch event handler, add the following line:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
When the handler has completed, execute the following:
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
It's up to you to figure out what to consider the end of the handler. If you're pushing or popping view controllers, you might add that second line to the viewWillAppear of the relevant view controllers. If you're displaying a modal view controller, you can use the completion handler of -[UIViewController presentViewController:animated:completion:].
Pretty much simple you can use make use of ExclusiveTouch property in this case
[self.navigationController.navigationBar setExclusiveTouch:YES];
This is a Boolean value that indicates whether the receiver handles touch events exclusively.
Setting this property to YES causes the receiver to block the delivery of touch events to other views in the same window. The default value of this property is NO.
If you want only one button to respond to touches at a time, you need to set exclusiveTouch for that button, rather than for the parent view.
Put this just after you add your bar button items.
for(UIView *temp in self.navigationController.navigationBar.subviews)
{
[temp setExclusiveTouch:YES];
}
or you can set exclusiveTouch individually for each UIBarButton while creating them.

Accessing the Status Bar

So, I'd like to receive touches from the status bar anywhere, any view, from the app. Well actually only specific views, like home screens and root view controllers say from a view of a tab view controller.
So my goal is to: hold down the status bar to dismiss the current view, like a back button.
The reason why I'm using this approach as a back button is because the app I am making is a utility, like fully functional apps within one app. Therefore I do not want to use up space on the navbar item to display a back button.
Other fissures would be nice, like swipe left/right or double tap, but mostly holding down. I've seen alternatives like using a UIScrollView and use the - scrollsToTop method. Hmm not what I am looking for.
Hope this can help you.
When you tap the top area, which has 44 height, the event would be triggered.
- (void)viewDidLoad{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(navigationBack:)];
[self.view addGestureRecognizer:tapGesture];
}
- (void)navigationBack:(UITapGestureRecognizer *)tapGesture {
CGPoint p = [tapGesture locationInView:self.view];
if (CGRectContainsPoint(CGRectMake(0, 0, self.view.frame.size.width, 44), p)) {
NSLog(#"this where you put you navigation back event");
}
}

UITableview scrollsToTop pressing UINavigationbar

I have a UIView with a UINavigationBar, a UITabBar and a UITableView.
When i press the status bar the UITableView scrolls to top because i have it set to TRUE.
I want to be able to do the same, by pressing the UINavigationBar like it happens in some apps. Setting the UITableView to scrollsToTop = TRUE only works if the user presses the StatusBar.
Method 1:
How about adding a TapGestureRecogniser on your UINavigationBar? This will only work if you dont have any buttons on your navigationBar.
//Create a tap gesture with the method to call when tap gesture has been detected
UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(navBarClicked):];
//isolate tap to only the navigation bar
[self.navigationController.navigationBar addGestureRecognizer:tapRecognizer];
//same method name used when setting the tapGesure's selector
-(void)navBarClicked:(UIGestureRecognizer*)recognizer{
//add code to scroll your tableView to the top.
}
and that's about it really.
Some people have found that their back button stops working when adding a tap gesture to the navigation bar, so you can do one of two things:
Method 2: Set the user interaction enabled to yes and set the tap gesture recogniser like shown in method 2 in detail.
Method 3: Use a UIGestureRecognizerDelegate method called gestureRecognizer:shouldReceiveTouch and make it return NO when the touch's view is a button, otherwise return YES. See method 3 in detail.
Method 2 from point 1: - feels dirty/hackish
[[self.navigationController.navigationBar.subviews objectAtIndex:1] setUserInteractionEnabled:YES];
[[self.navigationController.navigationBar.subviews objectAtIndex:1] addGestureRecognizer:tapRecognizer];
Method 3 from point 2: - a lot better, the right way
implement the UIGestureRecognizerDelegate protocol in your .h file, and in your .m file add the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// Disallow recognition of tap gestures when a navigation Item is tapped
if ((touch.view == backbutton)) {//your back button/left button/whatever buttons you have
return NO;
}
return YES;
}

Swipe gesture between view controllers in storyboards

I am looking to add a left and right swipe gesture to change between view controllers, is this possible and is there an easy way to do this in storyboards? Thanks :)
Storyboards allow you to set up segues between two view controllers. I would say start by attaching segues between the views, give it an identifier.
Then use something like
UISwipeGestureRecognizer * recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(myRightAction)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self addGestureRecognizer:recognizer];
to add a swipe recognizer to a view.
Then in the myRightAction method you'd want to do your segue call like
[self performSegueWithIdentifier: #"MySegue" sender: self];
to go to a view or dismiss it to leave the view.
You can use Navigation View Controllers to have a right and left transition animation. You can also make custom segues.
on Xcode 5 it is simpler, less code needed:
storyboard -> utility panel -> object Library -> drag and drop the Swipe Gesture Recognizer inside your scene
you MUST drag it into the view itself(where the background color appears) so you can see this connection: referencing outlet collections -> view
add the delegate by dragging the delegate's connection pin to the viewController
Show assistant editor -> add an action by ctrl + drag and drop on your delegate class viewController.m
inside that action write
[self performSegueWithIdentifier:#"mySegueIdentifier" sender:self];
Oops. Posted a comment on accident. Take a look at this answer: https://stackoverflow.com/a/14125580/1126783. You could just use a swipe gesture instead of buttons, and it uses storyboards.

IOS: disable gesture in a viewcontroller

In my app I have this situation:
I have my main viewcontroller where I alloc a "flipwiecontroller" and add its view in this way
self.flipViewController.view.frame = CGRectMake (...);
[self.view addSubview:self.flipViewController.view];
and at this flipViewController I add some gesture (as pangesture, swipegesture and tapgesture for some control that I use on it)
when I press a button in this view I alloc another viewcontroller "paintingviewcontroller" in this way
[self.view addSubview:paintingViewController.view];
in this second view controller I have some buttons and another function, but when I try to do a swipegesture or a tapgesture it recognize the events of my "flipviewcontroller"
I don't understand, if I add a view controller over another viewcontroller, why gesture of flipviewcontroller are active yet?
thnaks
Maybe you are disabling userIntercation on the paintingViewController, then, it's events are sent to his superview.
Also you can use [UIView removeGestureRecognizer:UIGestureRecognizer] to remove gestures.
How did you add the gesture recognizers? They should be added to the view, not the window. Perhaps that's the issue.
In case you have something like this:
[self.view.window addGestureRecognizer:panGestureRecognizer];
You should change it to this:
[self.view addGestureRecognizer:panGestureRecognizer];

Resources