2011-06-17 45 views
26

我有一个UINavigationController(使用类似于向导页面),这是我通过编程创建的,我需要显示一个“取消”按钮以取消任何UIViewController中的过程。将相同的按钮添加到UINavigationController中的所有视图控制器中

创建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; 

有人可以点亮这个吗?

在此先感谢。

回答

40

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

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

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

感谢您的澄清。我会去第三个选项并创建一个超类。 – Ozay

+2

虽然是迟到的评论,但您应该避免通过超类向班级提供功能。在开发过程中,你可能会有一些不喜欢继承额外功能的控制器子类。不仅如此,你的代码可能会变得更加复杂。 –

+0

感谢您对ViewControllers和NavigationItems之间关系的解释。 我的关于在segues(控制器开关)中存活的自定义按钮的方法将如下所示: * ViewControllers从BaseViewController继承。 * BaseViewController拥有NSMutableDictionary的属性 *此字典保持应显示在NavigationItem中的按钮的信息。 * BaseViewController更新当前的NavigationItems按钮组。 也许我的BaseViewController将通过协议连线。所以它会得到关于按钮配置的任何更改的通知。 – HBublitz

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]; 

正常的做法是将取消按钮添加到导航堆栈中每个视图控制器的导航项。上面的方法可以让你编写更少的代码变得更简单,但这只是一小撮攻击。

+0

问题:(1)按钮需要将其动作发送给某个视图控制器。当堆栈中有2个以上的VC时,你必须计算VC 1应该做什么,并且它们中的任何一个可能处于不确定状态。 (2)导航栏将与推送VC的VC共享,该VC以这种方式修改导航栏,这会导致取消按钮出现在不合适的地方。 (3)使用RTL语言可能不太好。我无法读取任何内容,所以我没有玩过UI如何为他们重新配置的问题。 –

+0

有效的担忧,正如我所说的那样,这有点破解。他真的应该让每个单独的视图控制器添加它自己的取消UIBarButtonItem并作出适当的响应。尽管如此,我认为你的担心并不多。他很可能在某些模式视图控制器中具有此向导,只需轻按即可轻松点击取消。无论状态如何,这都可以工作。 – hundreth

+0

你是对的,向导是在一个模态视图控制器,需要被解雇。我认为这可能是一个快速的方法。我想我会保持简单,使用继承将按钮添加到每个VC。 – Ozay

1

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

8

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

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

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

+0

我不知道这是一个好主意,将相同的BBI放到多个酒吧(iPad popover API让你显示一个视图一个BBI,所以大概它应该只在屏幕上一次一个地方;我不确定BBI是否神奇地包含对父母的引用) –

+0

使用'willShowViewController'在父视图中设置左键**将覆盖所有导航控制器中的后退按钮,当您推送viewController的后退按钮不会出现任何方式来解决此问题:http://stackoverflow.com/questions/30372135/add-buttons-to-uinavigationcontroller-subclass – Chlebta

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]; 
21

您也可以继承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]; 

} 
+1

谢谢。我以模态方式呈现一个'UINavigationController',并且我想要一个简单的Cancel按钮来应用它的所有屏幕。显然,我的使用案例对Google来说非常困难,而且不是一个受欢迎的应用案例。 – ray

+0

我喜欢你的风格! :) –

+0

并与sotryBoard如何设置'willShowViewController'以正确显示按钮? – Chlebta

5
  1. 创建CommonViewController
  2. 创建FirstViewController(从CommonViewController延伸)
  3. 创建SecondeViewController(延伸来自CommonViewController
  4. add函数在CommonViewController

那样

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和子类的

+0

@ mohamad我试着你的代码工作正常,但它无法点击该栏按钮。 –

+0

对上述我的回答感到抱歉。 请尝试下面的代码 在initializeCartBarButton函数后添加这2行:cartBarButton。title = @“cart”; [barButton setTarget:self]; [barButton setAction:@selector(goToCart :)]; (IBAction)goToCart:(id)sender { NSLog(@“”);(IBAction)goToCart:(id)sender { NSLog(@“”); } –

+0

是的,它已经解决了mohamad谢谢你.. –

2

删除此机能的研究这是我做到了与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) 
    } 
} 
相关问题