在UINavigationController中为所有视图控制器添加相同的按钮

时间:2011-06-17 16:53:08

标签: iphone ios uinavigationcontroller

我有一个UINavigationController(用作向导页面)我以编程方式创建,我需要显示“取消”按钮以取消任何UIViewController中的过程。

制作UINavigationController

FirstVC *firstVC = [[[FirstVC alloc] initWithNibName:@"FirstPage" bundle:nil] autorelease];
firstVC.delegate = self;

navigationController = [[UINavigationController alloc] initWithRootViewController:firstVC];
[self.view addSubview:navigationController.view];

添加取消按钮:

UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelRequestNewLeave:)];
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
[cancelButton release];

但是当我将第二页推到UINavigationController时,UINavigationBar上没有显示取消按钮。如果我回到第一页,取消按钮就在那里。所以,显然该按钮仅为第一个视图添加。我相信这是因为我不是子类UINavigationController,因为我需要在子视图中使用它。但我不知道如何在以编程方式创建的rightBarButtonItem中设置UINavigationController

navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;

有人可以对此有所了解吗?

提前致谢。

8 个答案:

答案 0 :(得分:40)

导航项是每个视图控制器。导航栏从视图控制器的导航项中绘制其内容,该视图控制器的当前框架视图对应于导航控制器堆栈顶部的视图控制器。

您基本上需要每个视图控制器在其导航项中粘贴取消按钮。您可以执行以下任何操作:

  • 将代码复制粘贴到所有相关的视图控制器中。
  • 将代码移动到实用程序函数或类中并调用它。
  • 为所有相关视图控制器创建一个公共超类,用于设置其子类的取消按钮。

答案 1 :(得分:22)

您也可以继承UINavigationcontroller并覆盖以下几种方法:

- (id)initWithRootViewController:(UIViewController *)rootViewController {
    self = [super initWithRootViewController:rootViewController];
    if (self) {
        [self setCloseButtonToController:rootViewController];
    }
    return self;
}

- (void)dismissController {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)setCloseButtonToController:(UIViewController *)viewController {
    UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(dismissController)];
    [viewController.navigationItem setRightBarButtonItem:closeItem];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [super pushViewController:viewController animated:animated];

    [self setCloseButtonToController:viewController];

}

答案 2 :(得分:8)

您可以在创建UINavigationControllerDelegate实例的类中采用UINavigationController协议。您也可以提前创建cancelButton,然后像这样实施navigationController:willShowViewController:animated:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    viewController.navigationItem.rightBarButtonItem = cancelButton;
}

您必须记住创建并按住cancelButton而不释放它。这也意味着cancelRequestNewLeave:必须是类中创建UINavigationController实例的方法,这正是我现在所想的。

答案 3 :(得分:5)

  1. 创建CommonViewController
  2. 创建FirstViewController(从CommonViewController扩展
  3. 创建SecondeViewController(从CommonViewController扩展
  4. 在CommonViewController中添加函数常用函数
  5. 喜欢那样

    <强> CommonViewController.h

    @interface CommonViewController : UIViewController
    
    -(void) initializeCartBarButton;
    
    @end
    

    <强> CommonViewController.m

    #import "CommonViewController.h"
    
    @interface CommonViewController ()
    
    @end
    
    @implementation CommonViewController
    
    -(void) initializeCartBarButton {
    
    
        UIBarButtonItem *cartBarButton = [[UIBarButtonItem alloc] init];
        cartBarButton.title = @"cart";
        [cartBarButton setTarget: self];
        [cartBarButton setAction: @selector(goToCart:)];
    
        self.navigationItem.rightBarButtonItem = cartBarButton;
        }
    
    - (IBAction) goToCart:(id)sender {
        NSLog(@"");
      }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
      }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
      }
    
    @end
    

    <强> FirstViewController.h

    #import <UIKit/UIKit.h>
    #import "CommonViewController.h"
    
    @interface FirstViewController : CommonViewController
    
    @end
    

    <强> FirstViewController.m

    #import "FirstViewController.h"
    
    @interface FirstViewController ()
    
    @end
    
    @implementation FirstViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self initializeCartBarButton];
    }
    @end
    

    <强> SecondViewController.h

    #import <UIKit/UIKit.h>
    #import "CommonViewController.h"
    
    @interface SecondViewController : CommonViewController
    
    @end
    

    <强> SecondViewController.m

    #import "SecondViewController.h"
    
    @interface SecondViewController ()
    
    @end
    
    @implementation SecondViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self initializeCartBarButton];
    }
    @end
    

    注意:您可以在CommonViewController的viewDidLoad中添加initializeCartBarButton的代码,并从CommonViewController和子类的

    中删除此功能

答案 4 :(得分:3)

这就是我使用UINavigationController子类的方法,它能够解除每个推入它的viewController。

class CustomNavigationController: UINavigationController, UINavigationControllerDelegate{

    //TODO: Use when we have more right bar button types.
    var rightBarButtonType: RightBarButtonType = .Close

    enum RightBarButtonType{
        case Close
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }

    // MARK: Private Functions
    private func addRightBarButtonTo(viewController: UIViewController){

        let barButtonItem: UIBarButtonItem!
        switch self.rightBarButtonType {
        case .Close:
            barButtonItem = UIBarButtonItem(image: UIImage(named: "ic_close_white"), style: .Done, target: self, action: #selector(CustomNavigationController.dismiss(_:)))

        }
        viewController.navigationItem.rightBarButtonItem = barButtonItem
    }

    // MARK: UINavigationController Delegate
    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        self.addRightBarButtonTo(viewController)
    }

    @objc func dismiss(sender: AnyObject){
        self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
    }
}

答案 5 :(得分:1)

您需要在每个视图控制器中添加按钮。你不能通过设置一次或在视图控制器之间共享一个(以合理的方式)来做到这一点。添加按钮的好地方是视图控制器的viewDidLoad方法。如果您觉得这会重复,可以为它们创建一个基本的UIViewConteoller子类。

答案 6 :(得分:0)

您可以将自定义“取消”UIButton直接添加到NavigationBar的视图中,而不是使用UIBarButtonItem。

UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.imageView = // Some custom image
cancelButton.frame = CGRectMake(...);  // Something far to the right.
[self.navigationController.navigationBar addSubview: cancelButton];

执行此操作的常规方法是将取消按钮添加到导航堆栈中每个视图控制器的navigationItem。上面的方法可以通过允许你编写更少的代码来简化它,但它只是一个小小的黑客。

答案 7 :(得分:0)

在rootview viewDidLoad方法中添加此代码,并在rootview控制器中实现cancelMethod。这将在所有视图控制器中可用。您可以通过更改按钮框来调整按钮位置。对于方向更改,您可以手动调整按钮的位置。

 UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [btnCancel addTarget:self
                        action:@selector(cancelMethod)
              forControlEvents:UIControlEventTouchDown];
        [btnCancel setBackgroundImage:[UIImage imageNamed:@"image"]  
        forState:UIControlStateNormal];
        btnCancel.frame = CGRectMake(280, 27, 45, 25);

    [self.navigationController.view addSubview: btnCancel];