iPhone: How do I override the back button in a Navigation Controller? - iphone

In my app I have a basic Navigation Controller. For all of my views, except one, the controller works as it should.
However, for one view in particular, I would like the 'back' button to not go back to the previous view, but to go to one I set. In particular it is going to go back 2 views and skip over one.
After doing some research I found that I can intercept the view when it disappears, so I tried to put in code to have it navigate to the page I would like:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//i set a flag to know that the back button was pressed
if (viewPushed) {
viewPushed = NO;
} else {
// Here, you know that back button was pressed
mainMenu *mainViewController = [[mainMenu alloc] initWithNibName:#"mainMenu" bundle:nil];
[self.navigationController pushViewController:mainViewController animated:YES];
[mainViewController release];
}
}
That didn't work, so does anyone have any ideas?
Thanks!!

In your code, you seem to be trying to push another view controller onto the stack, rather than pop an extra item off it.
Try this as your code that does the going back two levels:
NSArray *vcs = [self.navigationController viewControllers];
[self.navigationController popToViewController:[vcs objectAtIndex:[vcs count]-3];
Alternatively you could totally replace the back button with a button of your own? In your viewController:
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(doSomething:)];
self.navigationItem.hidesBackButton = YES;
self.navigationItem.leftBarButtonItem = item;
[item release];
Then you can write the doSomething: method to pop the two items off the stack, perhaps using the code I posted above.

Simple solution:
- (void)viewWillDisappear:(BOOL)animated {
//if true, back was pressed
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
//your logic
}
}

You can try implementing the UINavigationBarDelegate delegate. When the method -navigationBar:didPopItem: is called, you can pop an additional item from the UINavigationController, and thus pop two items at once.

UIButton *home = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *homeImage = [UIImage imageNamed:#"back.png"];
[home setBackgroundImage:homeImage forState:UIControlStateNormal];
[home addTarget:self action:#selector(LogOut)
forControlEvents:UIControlEventTouchUpInside];
home.frame = CGRectMake(0, 0, 69, 26);
UIBarButtonItem *button2 = [[UIBarButtonItem alloc] initWithCustomView:home];
[[self navigationItem] setLeftBarButtonItem:button2];
[button2 release];
button2 = nil;

Related

UINavigationController back and close button

I have a navigation controller. The controller works well and shows me the back button for go back to the window. But when I add this code for add the close button:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Chiudi"
style:UIBarButtonItemStylePlain target:self
action:#selector(dismissModalViewControllerAnimated:)];
self.navigationItem.rightBarButtonItem = doneButton;
[doneButton release];
}
...then the back button disappears, and I can only see the close button. Why?
THE PROBLEM was in
dismissModalViewControllerAnimated
I HAD TO USE
[self.navigationController dismissModalViewControllerAnimated:YES];
[self.navigationController popToRootViewControllerAnimated:NO];

How to dismiss pop over view in content view?

see the screen shot is clear to understand what I mean
you can see I add a navigationItem in my pop view
I wish I can dismiss the pop view
But it seems only tab the cell under the pop view
The pop view will dismiss,I try to add this method
[self.view removeFromSuperview];
It only remove the table view , the pop view frame is still there ,only without the content view
Any reply will be helpful : )
Thanks
Webber
/******EDIT******/
I use WEPopoverView into my project
And this is the code I create the pop view when I select the table view
if (indexPath.row==2) {
DaysOfWeek *popView = [[DaysOfWeek alloc]init];
UINavigationController *navPopView = [[UINavigationController alloc] initWithRootViewController:popView];
if (self.popoverController) {
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
else {
self.popoverController = [[[WEPopoverController alloc] initWithContentViewController:navPopView] autorelease];
CGRect frame = [tableView cellForRowAtIndexPath:indexPath].frame;
[self.popoverController presentPopoverFromRect:frame
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown|UIPopoverArrowDirectionUp
animated:YES];
}
}
/******EDIT2******/
I try to add Done button when I create the pop view
here is the code , But it only appear a navigation , no Done button
DaysOfWeek *popView = [[DaysOfWeek alloc]init];
UINavigationController *navPopView = [[UINavigationController alloc] initWithRootViewController:popView];
navPopView.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(hidePopView)];
While you add the popup view, set tag to that popupView and then, add them as subview,
then use:
for (UIView *tempView in [self.view subviews]) {
if ([tempView tag]==urTag) {
[tempView removeFromSuperview];
}
}
This retrieves all the subviews and then remove only your popupview
I think that simply releasing your self.popoverController will do the dismiss properly, including all the superviews.
You can also have a look at the dealloc method in WEPopoverController to see which views are involved and need to be removed:
[self dismissPopoverAnimated:NO];
[contentViewController release];
[containerViewProperties release];
[passthroughViews release];
Anyway, the only advantage I see is the possibility of calling dismissPopoverAnimated with YES.
Hope this helps.
EDIT:
How can you connect your done button to your controller?
Make your button accessible through a read-only property of DaysOfWeek; then in your controller, when you create DaysOfWeek, do:
DaysOfWeek *popView = [[DaysOfWeek alloc]init];
[propView.doneButton addTarget:self action:#selector(fullyDismissPopover) forControlEvents:UIControlEventTouchUpInside];
In fullyDismissPopover, you call release or call the sequence of functions highlighted above (but release would be better, I think).
DaysOfWeek *popView = [[DaysOfWeek alloc]init];
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
[doneButton addTarget:self action:#selector(hidePopView) forControlEvents:UIControlEventTouchUpInside];
popView.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:doneButton] autorelease];
UINavigationController *navPopView = [[UINavigationController alloc] initWithRootViewController:popView];
This also can figure out the problem !

setToolbarItems issue

I added toolbar to on screen of navigation based application using the following code
//Create an array to hold the list of bar button items
NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:3];
//Add buttons
//load the image
UIImage *buttonImage ;
buttonImage = [UIImage imageNamed:#"test.png"];
//create the button and assign the image for window width and level
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(WWL:) forControlEvents:UIControlEventTouchUpInside];
[button setImage:buttonImage forState:UIControlStateNormal];
//set the frame of the button to the size of the image (see note below)
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
//create a UIBarButtonItem with the button as a custom view
WindowWidthZoom = [[UIBarButtonItem alloc] initWithCustomView:button ];
[items addObject:WindowWidthZoom ];
[self setToolbarItems:items];
[[self navigationController] setToolbarHidden:NO animated:NO];
but when leave the screen , I noticed that the toolbar didn't disappear in the other screens , any suggestion how to hide it before leaving this screen to avoid its presence in other screens , and how to change its color to black
You might add the following to the -viewWillAppear method of all your other view controllers:
[self.navigationController setToolbarHidden:YES animated:NO];
In the view controller where you want the toolbar to appear, make sure you setToolbarHidden to NO also in the -viewWillAppear method. Doing so in the -viewDidLoad method is not enough because this method is not called every time a view appears. For example, when you hit the Back button of a navigation controller and return to a previous view controller, since that view controller has already been loaded, it may not need to load again (and so -viewDidLoad will not be called.)
Please change your last line code:
[[self navigationController] setToolbarHidden:NO animated:NO];
to:
[self setToolbarHidden:NO animated:NO];
And make sure call it in:
- (void)viewDidAppear:(BOOL)animated;

Putting a back button inside of a Modal view pushed by another modal view

Check this, im pushing a modal view inside of another modal view. But, im trying to put a button inside of this modal view, but without luck.
What im doing wrong?
Thanks!
CadastroViewController *addController = [[CadastroViewController alloc] initWithNibName:#"CadastroViewController" bundle:nil];
// This is where you wrap the view up nicely in a navigation controller
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:addController];
// You can even set the style of stuff before you show it
navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
navigationController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"OK" style:UIBarButtonItemStyleBordered target:self action:#selector(buy)];
// And now you want to present the view in a modal fashion all nice and animated
[self presentModalViewController:navigationController animated:YES];
// make sure you release your stuff
[navigationController release];
[addController release];
You'll have to add a new UINavigationItem to the navigationbar of the actual viewcontroller - NOT the navigation controller.
addController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"OK" style:UIBarButtonItemStyleBordered target:self action:#selector(buy)];
You should add your button in a
-(void) viewDidLoad of your CadastroViewController controller class
This will look like this:
- (void) viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:#"OK" style:UIBarButtonItemStyleBordered target:self action:#selector(buy)];
self.navigationController. leftBarButtonItem = button;
[button release];
}
[self presentModalViewController: navigationController animated:YES]; is ok in your example, just all other initializations you should do in viewDidLoad
It seems to me, that the problem is here:
[self presentModalViewController: navigationController animated:YES];
Instead try do this:
[self presentModalViewController: addController animated:YES];

How can I show a custom image in navigation bar back button instead of default buttons which are shown by nav bar itself

On navigating to any view in an app which has navigation controller implemented, it shows a back button to go to the previous view. Is there a way I can use custom image instead of the default one?
Yes you can.
You can control how the standard back button will look when another view controller is pushed on top of a given view controller by setting its navigation item's back bar button item (you can customize the title or use an image):
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = btn;
[btn release];
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithImage:yourImage style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = btn;
[btn release];
Note: you configure this in a "parent" view controller that may have other view controller(s) pushed on top of it. The configuration is done in the "parent" and the appearance of the back button is changed when some view controller is on top. Tapping the back button brings you back as expected.
You can also create your own UIBarButtonItem and set it as the leftButtonItem on the navigation bar on the current view controller:
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithImage:yourImage style:UIBarButtonItemStyleBordered target:self action:#selector(yourMethod:)];
self.navigationItem.leftBarButtonItem = btn;
[btn release];
Note: in this case, the back / left bar button item is changed for the current view controller (when it is on top). You must implement the yourMethod: method. If you simply want the button to go back, you have to handle popping the view controller yourself by calling [self.navigationController popViewControllerAnimated:YES];.
I found that none of the solutions actually solved the BACK UIBarButton and also provided its hidden behavior if the view controller is root.
-(void)popViewControllerWithAnimation {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if([self.navigationController.viewControllers objectAtIndex:0] != self)
{
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 26, 26)];
[backButton setImage:[UIImage imageNamed:#"back"] forState:UIControlStateNormal];
[backButton setShowsTouchWhenHighlighted:TRUE];
[backButton addTarget:self action:#selector(popViewControllerWithAnimation) forControlEvents:UIControlEventTouchDown];
UIBarButtonItem *barBackItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.hidesBackButton = TRUE;
self.navigationItem.leftBarButtonItem = barBackItem;
}
}
It almost works like a back button. With the exception of the transition animation (after the button is tapped and current view is popped off the navigation to the right).
The right way is to make a category.
#interface UINavigationBar (MyNavigationBar)
-(void)drawRect:(CGRect)rect;
#end
#implementation UINavigationBar (MyNavigationBar)
-(void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed:#"....."];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];