I am using an ABPeoplePickerNavigationController in my app and have overrode the navigation bar buttons to my own using UINavigationControllerDelegate.
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
navigationController.topViewController.searchDisplayController.searchBar.barStyle = UIBarStyleBlack;
navigationController.topViewController.navigationItem.leftBarButtonItem = nil;
navigationController.topViewController.navigationItem.rightBarButtonItem = nil;
UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:#selector(cancel:)];
navigationController.topViewController.navigationItem.leftBarButtonItem = cancelButtonItem;
UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(addItem:)];
navigationController.topViewController.navigationItem.rightBarButtonItem = addButtonItem;
}
This works fine. However, when I use the search controller and exit out of it, my top right button suddenly changes to a Cancel button (see image below). How can I fix this? Thanks in advance.
OK, just figured out how to fix this. I just added a notification to see when the keyboard will be hidden and added the button back to the navigation bar.
1) Declare and synthesize the property mainNavigationController:
#property UINavigationController *mainNavigationController;
2) In (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated, add:
mainNavigationController = navigationController;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onNotification:) name:UIKeyboardWillHideNotification object:nil];
3) Add the method onNotification:
-(void)onNotification:(NSNotification*)notification
{
UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(addItem:)];
mainNavigationController.topViewController.navigationItem.rightBarButtonItem = addButtonItem;
}
To fix this you have to implement the <UISearchDisplayDelegate> and in the navigationController:willShowViewController:animated: method set the delegate of the searchDisplayController to self viewController.searchDisplayController.delegate = self;
Related
I need to customise the back button of UINavigationBar. To handle this I subclassed UINavigationController and wrote the following piece of code, which results in two arrow side by side:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:#""
style:UIBarButtonItemStylePlain
target:nil
action:nil];
[backItem setImage:[UIImage imageNamed:kBackButton]];
[backItem setImageInsets:UIEdgeInsetsFromString(kImageInset)];
viewController.navigationItem.backBarButtonItem = backItem;
}
In this code the arrow shifts its position when the action sheet shows up.
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:#""
style:UIBarButtonItemStylePlain
target:self
action:#selector(popViewControllerAnimated:)];
[backItem setImage:[UIImage imageNamed:kBackButton]];
[backItem setImageInsets:UIEdgeInsetsFromString(kImageInset)];
viewController.navigationItem.leftBarButtonItem = backItem;
}
What would be the best approach to create back button where:
The arrow does not shift when action sheet shows up.
Two arrows are side by side.
My app is a tab bar app with many navigation controllers.
I want these navigation controllers to handle login/logout actions with a custom right bar button. So I've set up my tab bar in AppDelegate this way :
MyFirstViewController *firstViewController = [[MyFirstViewController alloc] init];
UIViewController *firstNavigationController = [[CustomNavigationController alloc]
initWithRootViewController:firstViewController];
MySecondViewController *secondViewController = [[MySecondViewController alloc] init];
UIViewController *secondNavigationController = [[CustomNavigationController alloc]
secondViewController]
initWithRootViewController:secondViewController];
....
[tabBarController setViewControllers:#[firstNavigationController, secondNavigationController]];
Then CustomNavigationController :
#implementation ConnectionNavigationController
- (void) viewDidLoad
{
[self displayConnectionButton];
}
- (void) displayConnectionButton
{
UIImage *portraitImage, *landscapeImage;
portraitImage = [UIImage imageNamed:#"conn.png"];
landscapeImage = [UIImage imageNamed:#"connLandscape.png"];
UIBarButtonItem *connButton = [[UIBarButtonItem alloc]
initWithImage:[portraitImage
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
landscapeImagePhone:[landscapeImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
style:UIBarButtonItemStylePlain target:self action:#selector(showConnectionPopup)];
self.navigationItem.rightBarButtonItem = connButton;
}
#end
I tried with viewDidLoad, viewDidAppear, viewWillAppear but nothing works, I can't get this button to show in the navigation bar. I also tried to add reloadInputViews or setNeedsDisplay. What should I do?
Thanks for your help
Edit : interface of CustomNavigationController
#interface ConnectionNavigationController : UINavigationController
- (void) displayConnectionButton;
#end
From what I understand you should add the displayConnectionButton method to the relevant UIViewController subclass and not to your UINavigationController subclass as this only contains the stack of view controllers.
E.g.
#implementation MyFirstViewController
- (void) viewDidLoad
{
[self displayConnectionButton];
}
- (void) displayConnectionButton
{
UIImage *portraitImage, *landscapeImage;
portraitImage = [UIImage imageNamed:#"conn.png"];
landscapeImage = [UIImage imageNamed:#"connLandscape.png"];
UIBarButtonItem *connButton = [[UIBarButtonItem alloc]
initWithImage:[portraitImage
imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
landscapeImagePhone:[landscapeImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
style:UIBarButtonItemStylePlain target:self action:#selector(showConnectionPopup)];
self.navigationItem.rightBarButtonItem = connButton;
}
#end
As a note if you put a breakpoint on your displayConnectionButton in your CustomNavigationController and po self.viewControllers I think you will get an empty array (i.e. no view controllers)
i have a UI Image picker and its being shown inside a UI popoverController, i need a back button on UIimage picker navbar, so i can go back to previous popover.
let me explain in details.
1) i have a popup in which i tap and raise a notification, this notification is read on a view controller where i want this camera image picker popup. following is my code
-(void)registerNotificationForCameraSource
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(mediaSourceCallback:) name:NOTIFICATION_FOR_CAMERA_SOURCE object:nil];
}
#pragma mark - Image picker Popover
-(void)mediaSourceCallback:(NSNotification *)notificationObj
{
capturedImages = [[NSMutableArray alloc] init];
pickerObj = [[UIImagePickerController alloc] init];
// [pickerObj setContentSizeForViewInPopover:CGSizeMake(320,480)];
pickerObj.delegate = self;
if ([notificationObj.object isEqualToString:#"UIImagePickerControllerSourceTypeCamera"])
{
pickerObj.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerObj.modalPresentationStyle = UIModalPresentationFullScreen;
pickerObj.showsCameraControls = YES;
[self presentViewController:pickerObj animated:YES completion:nil];
}
else
{
[[UINavigationBar appearanceWhenContainedIn:[ApplicationDiscriptionPopupViewController class], nil] setBarTintColor:[UIColor redColor]];
pickerObj.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"Back" style:UIBarButtonItemStyleDone target:self action:#selector(imagePickerBackButtonTapped)];
[pickerObj.navigationController.navigationBar setBarTintColor:[UIColor redColor]];
[pickerObj setNavigationBarHidden:NO animated:YES];
//navigationControllerObj = [[UINavigationController alloc] initWithRootViewController:applicationDiscriptionPopupViewControllerObj];
_popoverControllerObj.popoverContentSize = CGSizeMake(320,480);
pickerObj.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[pickerObj presentedViewController];
[_popoverControllerObj setContentViewController:pickerObj animated:YES];
}
}
-(void)imagePickerBackButtonTapped
{
[pickerObj popToViewController:applicationDiscriptionPopupViewControllerObj animated:YES]; }
pickerObj is UI Image picker
applicationDiscriptionPopupViewControllerObj is view controller of my previous popover view. from where i came. now i wana go back to this view in the popup, when i tap on back button in nav bar.
but i dnt hav any nav bar. plz help
If you are adding a UIImagePickerController via presentViewController inside a UIViewController then you should see the default navigation bar. You should implement :
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
UINavigationItem *navBarTopItem;
// you cannot add a custom back button with native back button look like, so use image over
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"back_arrow.png"]
style:UIBarButtonItemStyleBordered
target:self
action:#selector(backAction)];
navBarTopItem.title = #"Albums"; // "Camera
navBarTopItem.leftBarButtonItem = backButton;
}
Add a back button action handler
-(void)backAction{
[self.navigationController popViewControllerAnimated:YES];
}
Hope that answer ur Q.
If the text itself can't be changed and the button needs to be replaced then please also explain how to make the delegate method
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
still get called from replacement button?
Any help is greatly appreciated.
After some fiddling this worked:
Include UINavigationControllerDelegate in object .h file. Add the following to .m file:
- (void) showAddressBook {
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
// use delegate to change cancel text to done on picker that pops up
picker.delegate = self;
[self presentViewController:picker animated:true completion:nil];
}
// replace button now that controller is initialized
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if([navigationController isKindOfClass:[ABPeoplePickerNavigationController class]]) {
UIBarButtonItem *obbi = navigationController.topViewController.navigationItem.rightBarButtonItem;
UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:obbi.target action:obbi.action];
navigationController.topViewController.navigationItem.rightBarButtonItem = bbi;
}
}
How can i add method to UINavigationbar back button, so whenever I click that back button I need to check some values and show UIAlertView? Is there any option for this?
i tried this method but its working for me
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
//show alert
}
and also this method but both are not woking
-(void) viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
// back button was pressed. We know this is true because self is no longer
// in the navigation stack.
NSLog(#"hi");
}
Yes you can
In viedDidLoad
UIBarButtonItem * backBtn = [[UIBarButtonItem alloc]initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(goBackToAllPets:)];
self.navigationItem.leftBarButtonItem = backBtn;
write following function to check condition
-(void)goBackToAllPets:(id)sender
{
if(/*check condition*/)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:#"message" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
alert.tag = 0;
[alert show];
}
else
{
[self.navigationController popViewControllerAnimated:YES];
}
}
Suppose you have two controllers - Controller1 and Controller2.
Controller2 is pushed from Controller1. So before pushing the Controller2 on the navigationController from Controller1
Controller2 *controller2 = [[[Controller2 alloc] init]autorelease];
self.navigationItem.hidesBackButton = YES;
Now, in the viewDidLoad: method of Controller2, add the following snippet
UIBarButtonItem *backBarButtonItem =[[[UIBarButtonItem alloc]initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(goBackToAllPets:)]autorelease];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
and in the backButtonClicked method, you can perform the checks you want to.