iOS 7 Back Button Pop Gesture - iphone

In iOS 7 there's the new swipe to pop gesture: You swipe from left to right on the left side of your screen and the UINavigationController pops back to the previous UIViewController.
When I create a custom back button like this, the swipe to pop gestures doesn't work anymore:
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStyleBordered target:self action:#selector(navigateBack)];
[customBackButton setBackButtonBackgroundImage:barBackBtnImg forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[customBackButton setBackButtonBackgroundImage:barBackBtnImgHighlighted forBarMetrics:UIBarMetricsDefault];
self.navigationItem.backBarButtonItem = customBackButton;
How can I use a custom back button and have the native swipe to pop gesture?
Update:
That's what's happening in navigateBack:
- (void)navigateBack {
[self.navigationController popViewControllerAnimated:YES];
}

There is no need to add your own gesture recognizer. The UINavigationController already does that for you.
You need to set the delegate for the interactivePopGestureRecognizer before enabling it.
Do the following two things:
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
[self.navigationController.interactivePopGestureRecognizer setEnabled:YES];

Just add the following line of code:
[self.navigationController.interactivePopGestureRecognizer addTarget:self action:#selector(handleGesture:)];
You can add your own UIGestureRecognizer and pop the UIViewController yourself. See the docs for further info.

I use
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:#"nav_back.png"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:#"nav_back.png"]];
[UIBarButtonItem.appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -64) forBarMetrics:UIBarMetricsDefault];

To avoid crashes you have to be careful how you add and remove your custom back selector. The reason is that the navigation controller stays around while you pushing popping controller.
As already stated after adding your custom back button+selector, you should do the following in viewDidApear.
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)])
{
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
[self.navigationController.interactivePopGestureRecognizer addTarget:self action:#selector(navigateBack)];
}
Then in viewWillDisapear do
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)])
{
[self.navigationController.interactivePopGestureRecognizer removeTarget:self action:#selector(performCompletion)];
}
The timing of these calls is a key. You can run into crashes otherwise, see more details on the reason in here

There is a new gesture recognizer UIScreenEdgePanGestureRecognizer. You can add it to your view and handle respectively (call navigateBack), replicating view controllers navigation behaviour.

What did you do in "navigateBack" ?
Use this method like this :
- (void)navigateBack
{
[self.navigationController popViewControllerAnimated:YES];
}

try adding this into the custom back button
self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;

Related

iOS 7 Custom Back Button disappears after modal ViewController disappeared

I'm adding a custom back button to a UINavigationBar in UIViewController like follows:
-(void)viewDidLoad {
UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:#" " style:UIBarButtonItemStyleBordered target:self action:#selector(navigateBack)];
[customBackButton setBackButtonBackgroundImage:barBackBtnImg forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[customBackButton setBackButtonBackgroundImage:barBackBtnImgHighlighted forBarMetrics:UIBarMetricsDefault];
self.navigationItem.backBarButtonItem = customBackButton;
}
It works perfectly until I push a modal UIViewController and dismiss it again. What happens is that the standard iOS 7 back button is drawn over my custom back button.
This looks like an iOS 7 bug. Any idea how to work around it?
If you move your code to viewWillAppear:(BOOL)animated it should work. It's somewhat a hack, but it should work.

UINavigationController subclass with custom back button

I know I can set custom back button from the view controller itself, something like:
- (void)setBackButton
{
UINavigationBar* navBar = self.navigationController.navigationBar;
UIButton* backButton = [navBar backButtonWith:[UIImage imageNamed:#"navigationBarBackButton.png"]
highlight:nil
leftCapWidth:14.0];
[backButton addTarget:self action:#selector(backButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease];
}
- (void)backButtonTapped:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
The problem is that I need to do it for all my view controllers...
One solution is to put this code in some BasicViewController and all my view controllers will subclass it.
But my question is can I subclass the UINavigationCotroller itself and set it's nab bar left button to this custom button?
The right way to do this is using UIAppearance
It provides methods on UIBarButtonItem such as
- (void)setBackButtonBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
and
- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
No. It would be better to have a custom UIViewController that handles this behavior.

iPhone custom navigation bar with custom UIBarButtonItems

I'm trying to create a custom navigation bar with title and two custom baritems.
What I've done so far:
1. subclass a UINavigationBar
2. override -(void) drawRect:(CGRect)rect method, to draw image as a background
Now I get stuck when making right bar button item.
In my CustomBar class I've overriden pushNavigationItem method as follows:
- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated {
[super pushNavigationItem:item animated:NO];
item.rightBarButtonItem.customView.frame = CGRectMake(250, 5, 60,30);
}
and in my view controller I've done something like:
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationController.navigationItem.rightBarButtonItem = barButton;
[self.navigationController.navigationBar pushNavigationItem:self.navigationItem animated:NO]
but I always get SIGABRT when calling
[super pushNavigationItem:item animated:NO];
If I leave that line out, everything runs fine, but there is no button in the navigation bar.
What is the proper way to add custom bar button item to custom navigation bar?
EDIT:
For clarification, I've added an image.
This is what I need.
I'm trying to create the logout button on the right
Have you tried removingnavigationController while setting the item ? I used to do that for setting the title, never used to get the title.
Try [[self navigationItem] setRightBarButtonItem:yourButton];
In your case :
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationItem.rightBarButtonItem = barButton;`

iPhone: Navigate to another view with transition style and Back button set

I have following code which add BackButton on my view's navigation item's tabbar. It works fine.
// Add back button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
[view.navigationController setNavigationBarHidden:NO animated:YES];
view.navigationItem.backBarButtonItem = backButton;
view.navigationController.navigationBar.barStyle = UIBarStyleBlack;
[backButton release];
I use following line to navigate to my new view controller but it gets presented with default animation.
[view.navigationController pushViewController:viewController2 animated:YES];
I want to change the way it gets presented so I tried to do it following way.
[viewController2 setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[view.navigationController presentModalViewController:viewController2 animated:YES];
This works fine but I lost my BackButton..!! Is there anyway to present my new view controller with specific transition style and also keep my back button as is?
Thanks.
I found the answer to your question. Put a navigation bar on your viewController2 and add a bar button to it using either interface builder or using code. Then in the action of button press
In your viewController2.m write this function and link it up with the button press if you have added the bar button through interface builder.
-(void) backButtonPressed : (id) sender
{
[self dismissModalViewControllerAnimated:YES];
}
This should solve your problem.
Doing a pushViewController will carry forward the navigationBar and all for you but in your case presenting a viewController as modalViewController will not give you the navigationBar by default so you have to add it manually in your modalViewController which is viewController2 in your case.
Please let me know if you are still facing problems. We can fix it soon and save you some time and frustration.
Cheers!!!

Back button on UINavigationController

I know that it could seem strange but i need to add a back button on the navigation Bar of the first navigationController's view. I tried like this:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Foo" style:UIBarButtonItemStyleBordered target:self action:#selector(foo:)];
self.navigationItem.backBarButtonItem=backButton;
if instead of backBarButtonItem i write leftBarButtonItem the button is showed. My problem is that i need an arrow button as the normal back button. Is this possible?
Usually this works out of the box, but sometimes with modal views / action sheets you may need this. Just before you instantiate your viewcontroller and push it onto navigationcontroller stack, try
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Back" style: UIBarButtonItemStyleBordered target: nil action: nil];
[[self navigationItem] setBackBarButtonItem: newBackButton];
[newBackButton release];
DetailViewController *detailVC = [[DetailViewController alloc]init];
[self.navigationController pushViewController:detailVC animated:YES];
[detailVC release];
I don't think you can do that on the first NavigationController view, because you need to set the backBarButtonItem property in the parent controller, before the child controller is pushed. Also, according the to the Apple docs, the target & action of the backBarButtonItem must be nil.
This question about creating a left-arrow button on a UIToolbar may give you some ideas of how you could work around this using a custom image (for the leftBarButtonItem).
or you could also do the following - I prefer this method. I got this from a different post.
Use following psd that I derived from http://www.teehanlax.com/blog/?p=447
http://www.chrisandtennille.com/pictures/backbutton.psd
Then I just create a custom UIView that I use in the customView property of the toolbar item.
Works well for me.
Hope that helps a little
Of course you can do this. You just need to change the leftBarButtonItem's title to back
then you will get a nice left arrow button with the title back. Then you just change the selector to actually perform a method when the button is clicked. So #selector(foo:)
Here some code on how to achieve the above:
self.navigationItem.leftBarButtonItem.style = UIBarButtonItemStyleDone;
self.navigationItem.leftBarButtonItem.title = #"Back";
self.navigationItem.leftBarButtonItem.target = self;
self.navigationItem.leftBarButtonItem.action = #selector(endTextEnteringButtonAction:);
Let me know if that helps.
Apple Document says:
When this navigation item is immediately below the top item in the stack, the navigation controller derives the back button for the navigation bar from this navigation item.
So If your navigation item is the top of the Stack (as we are talking here) you can't add the back button to the navigation controller, simply because no place he can navigate back to it because it's the top item in the stack.
Updated Answer :
After I searched I found work a round to make a back button in your root view controller in Navigation controller in these link
It's very simple :)
[self.navigationItem setHidesBackButton:YES animated:YES];
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:#"Start" style:UIBarButtonItemStyleBordered target:self action:#selector(initializeStuff)];
self.navigationItem.leftBarButtonItem = backButton;