自定义导航后退按钮,在swift3中具有自定义标题

时间:2017-07-10 18:27:46

标签: ios swift uinavigationbar

我需要使用自定义后备图像和自定义标题实现导航栏。例如:如果我在“使用Facebook登录”页面,我需要显示除了自定义后退图像之外的“使用Facebook登录”。为此,我遵循这样的代码:

.visible{
display: block;
opacity: 1;}

nav{position: absolute;
z-index: 102;
width: 100%;
height: 100vh;
opacity: 0;
transition: opacity 4s;
background-color: $accent-blue;
display: none;
border: 10px solid $accent-yellow;
box-sizing: border-box;}

但我得到的输出是这样的:

enter image description here

注意:标题属于当前页面。

如何实现这一目标?

2 个答案:

答案 0 :(得分:0)

如果后面标题太长,iOS会将其更改为“返回”。

但是,如果您添加一个左栏按钮项目 - 您可以将其设置为更长的长度。

long back

来自Apple文档:https://developer.apple.com/documentation/uikit/uinavigationcontroller

  

如果后退按钮的标题太长而无法放入可用空间,导航栏可能会将字符串“Back”替换为实际按钮标题。仅当前一个视图控制器提供后退按钮时,导航栏才会执行此操作。如果新的顶级视图控制器有一个自定义左栏按钮项 - 一个对象   leftBarButtonItem    要么   leftBarButtonItems    导航栏的属性 - 导航栏不会更改按钮标题。

要执行此操作,请转到Storyboard,在Interface Builder中,将Bar Button Item拖动到导航栏中并设置其标题。

*请注意,您需要将其连接到视图控制器以弹出它。

 @IBAction func pop(_ sender: UIBarButtonItem) {
    _ = navigationController?.popViewController(animated: true)
}

答案 1 :(得分:0)

你会发现很多StackOverflow尝试回答这个(非常常见的)问题,而我发现的最佳方式也相当复杂。您必须为应用中的每个 UINavigationControllerUINavigationBarUINavigationItem执行此操作,这很痛苦。

Apple 想要你如何做到(据我所知)

  1. 对于故事板中的UINavigationBar,请将后退后遮罩值(在“属性”检查器中)设置为自定义图像的名称。< / LI>

    UINavigationBar Attributes inspector

    1. 对于每个视图控制器的UINavigationItem,请将其后退属性值设置为空字符串或单个空格。
    2. UINavigationItem Attributes inspector

      够简单吧? 不。首先,空字符串或单空格后退标题并不总是受到尊重。如果你有几十个甚至几百个视图控制器怎么办?如果您的应用程序有多个UINavigationController,该怎么办?如果您以编程方式设置配置视图控制器(或至少是其导航项),该怎么办?然后就不那么容易了。

      StackOverflow如何认为你应该这样做

      我不会链接到推荐这种做事方式的所有SO答案。我将其概括为:

      1. 使用UINavigationItem.setHidesBackBarItem(_:animated:)隐藏导航项的后退按钮。

      2. 使用自定义后备图片和空标题创建UIBarButtonItem,然后将其添加到导航项leftBarButtonItem

      3. 坐下来等待用户错误报告涌入,抱怨您的应用不支持滑动以导航回来。

      4. 或者,如果您想要聪明,请将导航控制器的interactivePopGestureRecognizer附加到自定义左栏按钮项目。这个通常有效,但感觉就像是在将来的版本中可能会破解的黑客。如果你对此感到满意,那么你可以在这里停止阅读。

      5. 认为你应该这样做

        如果你有一个很多的视图控制器(我们的应用程序有200多个)和/或以编程方式和故事板配置的混合VC,这可能最终会更容易。

        1. 创建UINavigationBar的子类,并将其设置为故事板和代码中所有导航栏的类。 (如果您在代码中执行此操作,请注意导航栏是只读属性;它可以在导航控制器的初始化程序中设置 。)

        2. UINavigationBar管理一堆UINavigationItem s,一个用于UINavigationController堆栈上的每个视图控制器,并使它们与视图控制器保持同步。换句话说,当您将视图控制器推送到导航控制器时,该视图控制器的导航项也会被推送到导航栏,并在弹出VC时弹出。当导航栏按下或弹出一个项目时,它会使用新的最顶层项目的titletitleView和/或按钮项属性来设置配置自己的标题视图和按钮,并使用标题导航项目紧靠最顶层的以配置其后退按钮和后退图像。如果下一个项目的titlenil,则导航栏会使用默认值“返回”。你不希望这样。如果您可以在故事板中将后退属性设置为空或单空格字符串,那么您应该能够在代码中执行相同的操作,对吧? 错误。后面的文字不是UINavigationItem中的公共财产!的 WTF吗

        3. 相反,您必须将next-to-topmost项的标题设置为空字符串。 “可是等等!”你说,“这不是永久性地改变下一个项目的标题,所以当我导航回那个视图控制器时,它的标题会说”返回“而不是它的原始标题吗?你是对的。你能做什么?在UINavigationBar的子类中,添加一个Optional标题字符串数组,如下所示:

        4. var navigationItemTitles = [String?]()

          (为什么选择?因为导航项可能包含自定义titleView而非title。)

          1. 覆盖导航栏的pushNavigationItem(_:animated:)popNavigationItemAnimated(_:),以便他们分别修改和恢复导航项的标题:

            override func pushNavigationItem(_ item: UINavigationItem, animated: Bool) {
                super.pushNavigationItem(item, animated: animated)
            
                // Store the new back item's title, then set its title to
                // an empty string.
                if let backItem = backItem {
                    navigationItemTitles.push(backItem.title)
                    backItem.title = ""
                }
            }
            
            override func popNavigationItemAnimated(_ animated: Bool) {
                super.popNavigationItemAnimated(animated)
            
                // Restore the new top item's title.
                if navigationItemTitles.count > 0 {
                    topItem?.title = navigationItemTitles.popLast
                }
            }
            
          2. 注意事项

            这是我发现这是万无一失而且不是hacky的唯一方法。如果Apple只是简单地将导航项的 Back 属性设置为可公开设置,那么可以避免很多这样的事情。

            (对于它的价值,不仅我们的应用程序有200多个视图控制器,它还有多个导航控制器,具有不同的导航栏外观和感觉。这是另一层复杂性。)