How to create backBarButtomItem with custom view f

2020-01-27 00:28发布

I have a UINavigationController into which I push several views. Inside viewDidLoad for one of these views I want to set the self.navigationItem.backBarButtonItem to a custom view (based on a custom image). I don't know why, but it doesn't seem to work. Instead, I get the standard "back" button.

UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 63, 30)];
[backButton setImage:[UIImage imageNamed:@"back_OFF.png"] forState:UIControlStateNormal];
[backButton setImage:[UIImage imageNamed:@"back_ON.png"] forState:UIControlStateSelected];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.backBarButtonItem = backButtonItem;
[backButtonItem release];
[backButton release];

I tested with a standard title and it worked. What is wrong with the above code ?

self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Prout" style:UIBarButtonItemStyleDone target:nil action:nil] autorelease];

Thanks for any help on this.

标签: cocoa-touch
14条回答
劳资没心,怎么记你
2楼-- · 2020-01-27 00:50

The navigationController's backBarButtonItem is set on the item whose title you're trying to affect.

i.e. in Page 1's view controller, say, viewdidLoad:

self.title = @"Page 1 of 4";

self.navigationItem.backBarButtonItem =
[[[UIBarButtonItem alloc] initWithTitle:@"Page 1"
                                  style:UIBarButtonItemStyleBordered
                                 target:nil
                                 action:nil] autorelease];

You would not override this in Page 2.

Documentation for UINavigationItem : backBarButtonItem makes this clear:

When this item is the back item of the navigation bar—when it is the next item below the top item—it may be represented as a back button on the navigation bar. Use this property to specify the back button. The target and action of the back bar button item you set should be nil. The default value is a bar button item displaying the navigation item’s title.

查看更多
别忘想泡老子
3楼-- · 2020-01-27 00:52

My Logic:

  1. Create a custom button (aka a custom view subclass)
  2. Initialize a barbutton item with the custom button/view
  3. Add an action that allows us to "go back" to our previous view controller
  4. Set the left bar button item to this custom bar button item you created
  5. Hide the back bar button item of the view controller you're pushing to

Step 3 was important. I figured the cleanest way to simulate the "go back" was to just utilize UINavigationController's method (popViewControllerAnimated:). So, I just add that action to the navigationController of the viewController I'm pushing (viewControllerToPush) like so:

[navItemButton addTarget:viewControllerToPush.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];

Example:

UIViewController *viewControllerToPush = [[UIViewController alloc] init];
UIImage *navImage = [UIImage imageNamed:@"your_back_button_image"];

UIButton *navItemButton = [UIButton buttonWithType:UIButtonTypeCustom];
[navItemButton setImage:navImage forState:UIControlStateNormal];
[navItemButton setImage:navImage forState:UIControlStateHighlighted];
[navItemButton setFrame:CGRectMake(0, 0, navImage.size.width, navImage.size.height)];

[navItemButton addTarget:viewControllerToPush.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];

UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:navItemButton];

viewControllerToPush.navigationItem.leftBarButtonItem = barButtonItem;
viewControllerToPush.navigationItem.hidesBackButton = YES;
[self.navigationController pushViewController:viewControllerToPush animated:YES];
查看更多
甜甜的少女心
4楼-- · 2020-01-27 01:00

I never been able to create a proper UIBarButtonItem with custom view and setBackBarButtonItem.

Here's the solution i found : let net UINavigationControllerDelegate handles everything! The trick here is to call the popViewControllerAnimated: method of the viewController.navigationController so you don't have to create any custom method.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if([navigationController.viewControllers count ] > 1) {
        UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0,0,70,35)];
        UIButton *myBackButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
        [myBackButton setFrame:CGRectMake(0,0,70,35)];
        [myBackButton setImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal];
        [myBackButton setEnabled:YES];
        [myBackButton addTarget:viewController.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
        [backButtonView addSubview:myBackButton];
        [myBackButton release];
        UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
        viewController.navigationItem.leftBarButtonItem = backButton;
        [backButtonView release];
        [backButton release];
    }
}
查看更多
劫难
5楼-- · 2020-01-27 01:00

Set the backBarButtonItem before pushing the viewController with the navigationController. Setting the backBarButtonItem in viewDidLoad doesn't work.

Say I have MyTableViewController. When the user taps a particular row I want to push AnotherViewController using the navigationController. The code looks something like this:

// in MyTableViewController's tableView:didSelectRowAtIndexPath method...
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] 
                               initWithImage:[UIImage imageNamed:@"yourImage.png"]
                                       style:UIBarButtonItemStyleBordered 
                                      target:nil 
                                      action:nil];

self.navigationItem.backBarButtonItem = backButton;
[backButton release];

[self.navigationController pushViewController:anotherViewController];

When anotherViewController is displayed the back button in the navigation bar will have @"yourImage.png" and the default back button style (rectangular arrow). Also note it's fine to pass nil as target. The button behaves like the back button.

查看更多
Juvenile、少年°
6楼-- · 2020-01-27 01:00

Even though is already answered this worked for me:

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"backArrow.png"] style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];

BTW: even in iOS4 initializing my back button with initWithCustomView: didn't work for me. ;(

查看更多
姐就是有狂的资本
7楼-- · 2020-01-27 01:03

I would be willing to bet that this is a bug on Apple's part as I am running into the exact same problem. The reason being is that I can get a custom UIBarButtonItem to appear, but only when I don't try to use the initWithCustomView: method. Per the API, the navigation controller checks the following things when a new view controller is pushed:

  1. If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the leftBarButtonItem property of the view controller’s navigation item.
  2. If the top-level view controller does not have a custom left bar button item, but the navigation item of the previous view controller has a valid item in its backBarButtonItem property, the navigation bar displays that item.
  3. If a custom bar button item is not specified by either of the view controllers, a default back button is used and its title is set to the value of the title property of the previous view controller—that is, the view controller one level down on the stack. (If there is only one view controller on the navigation stack, no back button is displayed.)

My case (as well as yours) is 2. I specify code exactly the same as yours (i.e., creating a UIButton, setting its image properties for various states, creating a UIBarButtonItem, initializing it with the UIButton, then setting my current view controller's backBarButtonItem property to the UIBarButtonItem); however, when I later push my view controller, nothing at all is displayed on the left-hand side of my navigation controller. Strangely, I can click where the "Back" button should be, and it pops the view controller.

Interestingly, if I create a UIBarButtonItem using the initWithTitle:style:target:action: method instead of the initWithCustomView: method, it does show a custom button with a custom title. Also, as Travis mentioned, using the leftBarButtonItem property instead works just fine. I'd rather adhere to the sanctioned logic, however, by specifying the "Back" button for the current view controller -- to be displayed later when a new view controller is pushed -- instead of creating a left button for the next view controller, which, arguably, should have no concern for anything pertaining to the view controller that came before it. :-\

查看更多
登录 后发表回答