【问题标题】:Override back button in navigation stack while keeping appearance of default back button?覆盖导航堆栈中的后退按钮,同时保持默认后退按钮的外观?
【发布时间】:2011-02-22 23:48:35
【问题描述】:

我如何只为一个视图覆盖后退按钮(不是为不同视图中存在的所有后退按钮),以便在单击后退按钮时显示根视图控制器?

【问题讨论】:

  • 你不能完全按照你的意愿去做。您必须执行其他两个答案提供的类似操作。如果您想保留 back 的所有特征,但要覆盖有时会发生的情况,请选择 nacho4d 的答案。否则,更喜欢 Mike Bretz 的回答。

标签: uinavigationcontroller


【解决方案1】:

您需要替换后退按钮并关联一个动作处理程序:

- (void)viewDidLoad {
    [super viewDidLoad];

    // change the back button to cancel and add an event handler
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@”back”
                                                                   style:UIBarButtonItemStyleBordered
                                                                  target:self
                                                                  action:@selector(handleBack:)];

    self.navigationItem.leftBarButtonItem = backButton;
}

- (void)handleBack:(id)sender {
    // pop to root view controller
    [self.navigationController popToRootViewControllerAnimated:YES];
}

【讨论】:

  • 您好,感谢您的回答,但我想保留后退按钮样式并覆盖后退按钮实现,而不是创建新按钮。
  • Apple 指南不允许更改 UI 元素的预期行为,例如后退按钮。当 iOS 用户看到“正常”的后退按钮样式时,她期望正常的后退按钮行为。如果你想改变这种行为,你应该实现一个“普通”风格的按钮。
  • 嗨,有点老的答案,但我有一个问题:创建的按钮看起来不像正常的后退按钮(就像向左的箭头)?另外,改变它只会改变当前的视图控制器,对吗?其他 VC 会有正常的后退按钮,对吧?非常感谢。
  • @MikeBretz 也许只是一个过时的评论,但对于未来的读者。在某些情况下,您想覆盖该行为,因为您想提供到 previousViewController 的不同转换 - 在这种情况下,我认为覆盖此行为没有问题。它仍然在做用户期望的事情,只是采用了不同的代码路径。
  • 对我来说,如果用户退回,并且没有保存当前屏幕上的内容,我想显示一个弹出窗口,说“你确定要返回而不保存吗?”我确定这是可以接受的
【解决方案2】:

找到了一个同样保留后退按钮样式的解决方案。 将以下方法添加到您的视图控制器。

-(void) overrideBack{

    UIButton *transparentButton = [[UIButton alloc] init];
    [transparentButton setFrame:CGRectMake(0,0, 50, 40)];
    [transparentButton setBackgroundColor:[UIColor clearColor]];
    [transparentButton addTarget:self action:@selector(backAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.navigationController.navigationBar addSubview:transparentButton];


}

现在根据需要在下面的方法中提供一个功能:

-(void)backAction:(UIBarButtonItem *)sender {
    //Your functionality
}

它所做的只是用透明按钮覆盖后退按钮;)

【讨论】:

  • 您应该在离开视图控制器时从 superView 中删除 transparentButton,否则它将继续添加到其他视图控制器中的导航栏
  • @Brave 这不是一个好的解决方案。这是一个 hacky 解决方案。
  • @simonthumper:你能给出更好的解决方案吗?
  • 首先,如果你要这样做,你至少可以确保透明按钮的框架在-viewWillLayoutSubviews 中是正确的,否则你的后退按钮可能有一个大标题并且这个按钮赢了不要覆盖它。更好的解决方案是用带有图像和标签的自定义视图完全替换后退按钮以复制样式。还有无数其他更好的解决方案,这个本身就是 hacky。
  • pata nahi behen..(不认识妹子)
【解决方案3】:

老了,但正确答案是:

与其把你的 ViewController 压在所有其他的之上,你最好用 rootVC 和新的 VC 替换整个堆栈。

不是:

self.navigationController?.pushViewController(myVc, animated: true)

但是:

let vcStack = self.navigationController?.viewControllers
self.navigationController?.setViewControllers([vcStack![0],myVc], animated: true)

这样,在后面它只会popToRoot,因为它是堆栈中的前一个viewController

【讨论】:

    【解决方案4】:

    我有类似的问题,我成功地使用了 Sarasranglt 给出的答案。这是 SWIFT 版本。

        override func viewDidLoad() {
           let transparentButton = UIButton()
           transparentButton.frame = CGRectMake(0, 0, 50, 40)
           transparentButton.backgroundColor = UIColor.orangeColor()
           transparentButton.addTarget(self, action:"backAction:", forControlEvents:.TouchUpInside)
           self.navigationController?.navigationBar.addSubview(transparentButton)
        }
    

    而功能是

     func backAction(sender:UIButton) {
         // Some sction
     }
    

    【讨论】:

      【解决方案5】:

      另一种方法是采用UINavigationControllerDelegate协议。

      – navigationController:willShowViewController:animated:
      – navigationController:didShowViewController:animated:
      

      这些方法会在控制器出现时通知您,但您必须检查该控制器是您想要的控制器。

      【讨论】:

      • 您好,感谢您的回答,但是有什么方法可以覆盖 back 方法的实现。
      • 别忘了 self.navigatioNController.delegate = self;
      【解决方案6】:

      为了保持相同的外观,您可以使用:

      UIView *leftButtonView = [[UIView alloc]initWithFrame:CGRectMake(-12, 0, 105, 30)];
      
      UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeSystem];
      leftButton.frame = leftButtonView.frame;
      [leftButton setImage:[UIImage imageNamed:@"ic_system_back"] forState:UIControlStateNormal];
      [leftButton setTitle:@"title" forState:UIControlStateNormal];
      [leftButton.titleLabel setLineBreakMode:NSLineBreakByTruncatingTail];
      [leftButton.titleLabel setFont:[UIFont systemFontOfSize:16]];
      [leftButton setTitleEdgeInsets: UIEdgeInsetsMake(0, 8, 0, 0)];
      [leftButton addTarget:self action:@selector(handleBack:) forControlEvents:UIControlEventTouchUpInside];
      [leftButtonView addSubview:leftButton];
      
      UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc]initWithCustomView:leftButtonView];
      self.navigationItem.leftBarButtonItem = leftBarButton;
      

      【讨论】:

        【解决方案7】:

        遵循 Sarasranglt 在 Objective C 中使用透明按钮的方法,以及 Pavle Mijatovic 早期的 swift 版本,这里是一个 swift 4 版本:

        let transparentButton = UIButton()
        transparentButton.frame = CGRect(x:0, y:0, width:50, height: 40)
        transparentButton.backgroundColor = UIColor.clear
        transparentButton.addTarget(self, action:#selector(backAction(sender:)), for:.touchUpInside)
        self.navigationController?.navigationBar.addSubview(transparentButton)
        

        @objc func backAction(sender:UIButton) {
        // Some action
        }
        

        【讨论】:

          【解决方案8】:

          无需制作自定义按钮或没有任何 hack(transparentButton) 只需覆盖 'viewWillDisappear' 方法并在块内编写代码。

          override func viewWillDisappear(_ animated: Bool) {
                  // write your code...
          }
          

          【讨论】:

            【解决方案9】:

            使用此代码显示自定义后退按钮,请注意backBarButtonItem,然后再将其标记为重复答案。

            UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"< back"
                                                                           style:UIBarButtonItemStylePlain
                                                                          target:self
                                                                          action:@selector(handleBack:)];
            
            self.navigationItem.backBarButtonItem= backButton;
            

            干杯!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-10-25
              • 2017-01-06
              • 1970-01-01
              • 1970-01-01
              • 2022-01-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多