【问题标题】:Dynamically increase/decrease height of custom UINavigationBar动态增加/减少自定义 UINavigationBar 的高度
【发布时间】:2015-07-24 00:14:03
【问题描述】:

我关注了这个blog post,它解释了如何实现一个增加高度的自定义UINavigationBar,例如,如果您想在导航栏中放置其他将持续存在的栏内容下方的额外 ui 元素在堆栈上的导航之间。在您总是希望它增加高度的情况下,此代码非常有效。

在我的应用程序中,我需要在默认高度启动导航栏,然后在用户执行给定操作后增加它,添加更多内容。与 iTunes Store 中的歌曲信息和控件非常相似:

因此,如果BOOL 属性为NO,我会进行一些检查以不重新定位任何内容。当我将它设置为YES 时,我调用[self setNeedsDisplay],它将调用layoutSubviews 根据该布尔值适当地定位所有内容。 sizeThatFits 也被调用,我返回正确的高度。

问题是,我无法在initialize 中调用[self setTransform:CGAffineTransformMakeTranslation(0, -(NavigationBarHeightIncrease))];。相反,我同时将布尔值更改为YES。正因为如此,我所有的元素都上移了那个数量。但是如果我不调用setTransform,导航栏中的元素位于正确的位置,但导航栏本身的位置太低了,因此我添加到导航栏中的自定义视图显示在视图上方控制器的视图 - 它流血了,我添加的额外空间是黑色而不是导航栏的背景颜色。

如果我在initialize 中调用setTransform,当高度是默认高度时,元素会在不应该的时候向上移动。

那么,如何正确地动态更改UINavigationBar 子类的高度和位置?

【问题讨论】:

  • 我不建议改变 UINavigationBar-s 的高度或其实现,你永远不知道在下一个 iOS 版本之后 UINavigationBar 会发生什么变化,相反,我会使用自定义 UIView ,具有相同的背景/样式并将其附加到顶部布局指南,然后您可以轻松地操作您的视图而无需私有 apis
  • @ogres 不幸的是,我需要这个自定义视图在推送和弹出操作之间持续存在,所以我不能将它添加到视图控制器的视图中 - 它需要以某种方式绑定到导航控制器/栏。
  • 为什么不创建一个RootView控制器,然后在里面包含导航控制器呢?那么你可以维护视图
  • @ogres 也许这是一个解决方案。只是不确定这在实践中是如何工作的,愿意提供有关您如何处理它的答案吗?
  • 我只能给出一个建议,但不能真正回答你的问题,我已经尝试过类似的方法,但仅限于 UITabBarViewController,不确定它是否也适用于 UINavigation,例如:创建 UIViewController ,创建 UINavigationViewController (你当前的根视图),在添加 UINavigationvc-s 视图作为 uiviewcontroller 的子视图,并将 uinavigationvc 作为 uiviewcontroller 的子控制器,然后看看它是否有效,现在你可以向 UIViewcontroller 添加任何视图,它将在所有导航中可用推动

标签: ios uinavigationbar


【解决方案1】:

正如 cmets 中所建议的那样,要实现自定义导航栏(不是本机控件的子类)在导航控制器中的控制器的推送和弹出之间持续存在的行为,您需要有一个带有自定义导航的控制器栏,然后是一个单一的嵌入式视图,它解析为UINavigationController,其视图控制器位于下方。然后,还需要将导航控制器的委托设置为根控制器,以便在推送和弹出子控制器时更新标题和其他属性。我在下面提供了这个故事板版本的屏幕截图:

【讨论】:

  • 我已将导航控制器的代理通过prepareForSegue 设置为self。我摆脱了导航控制器上的顶部栏。但是现在我如何从我现在隐藏的导航控制器的导航栏中获取元素到我的自定义导航栏中?仅设置委托并不能解决问题。
  • 您需要手动管理标题。使用导航栏中的现有数据(例如navigationController.navigationBar.topItem.title)获取当前标题,您可以在自定义导航视图中设置 UI 元素。这能回答你的问题吗?
  • 我可以在navigationController:willShowViewController: 中设置左/右栏按钮项目和标题,但是向后滑动手势不起作用,并且后退按钮不会出现在自定义导航栏。此外,由于导航栏从顶部布局指南开始,它不会到达状态栏下方,因此状态栏下方只有白色。
  • 是的,您需要为此自定义视图设计尽可能多或尽可能少的设计,以获得所需的高度变化。如果您想要 all 导航控制器的功能,这将是一件棘手的事情。如果它在您的设计约束中是允许的,我会让导航看起来有点不同,并且不会以各种方式反映本机 UI。我的帖子只是让你走上正确的轨道。有关更多信息,我会谷歌创建自定义导航栏。
  • 我明白了。问题是我需要完全相同的本机导航栏和行为,下面只显示另一个“栏”。自定义导航栏并不是我真正想要的。
【解决方案2】:

一个选项是在情节提要中创建一个 UIViewController,它只有您希望在导航栏下方显示的控制视图,其他所有内容都是透明的。这里的优点是您可以使用普通工具进行设计。使用约束将其放置在导航栏下方并设置视图的高度、宽度等。

当您希望显示控件时,可以创建此 UIViewController 的实例并从中删除内容视图并将其添加到屏幕上的视图层次结构中。

插入提取的基本视图有两个选项:

  1. 如果将此控制视图添加到视图控制器的顶部 导航堆栈(屏幕上的内容),它会在什么时候被覆盖 你推一个新的控制器。这不是你说的你想要的。

  2. 如果将此控件视图添加到 self.navigationController.view,则 它将在推送和弹出中持续存在。这就是你说的你想要的。

我使用这种方法提供弹出帮助气泡来描述屏幕上的内容。根据我是使用选项 1 还是 2,我可以在多次推送/弹出时持续提供帮助。

我从这个描述一般方法的教程中得到了这个想法:http://blog.typpz.com/2013/12/09/ios-sdk-create-a-pop-up-window/

该链接提供了有关如何调出视图和删除视图的完整代码示例。

这可以让您在 IB 中设计它,根据需要呈现和关闭它,并在导航序列中保持它。

希望这会有所帮助。

【讨论】:

  • 有趣的方法。我看到的唯一问题是它会掩盖底层视图。我需要下面的视图控制器调整它们的内容插图,或者将整个视图向下移动,这样新视图就不会覆盖它们的内容。
  • @Joey 一个选项是将表创建为包含 UITableView 的 UIViewController,而不是使用 UITableViewController。然后,您可以使用约束和偏移将 UITableView 的顶部固定到顶部布局指南。当您想要覆盖时,请更改代码中的约束。由于您对叠加层和表格有一个约束,您可以在其中设置动画。将叠加层放在导航栏后面(将叠加层添加到导航视图控制器内容视图的前面而不是末端),您会看到叠加层从下方滑下吧台和桌子一起向下滑动。
  • @Joey 或者更简单地在表格顶部添加一个与叠加层高度相同的空白行并重新加载 8^)。
  • 如果我只使用单个视图控制器,这将起作用,但是一旦我推送不同的视图控制器,它就不会对自定义导航栏产生约束,因此它的内容将被掩盖。
  • @Joey 正确。您将需要一种机制,以便任何控制器都可以找到覆盖何时到位,并在其viewWillAppear 中采取必要的步骤将顶部向下推。我想在扩展导航栏时,您假设顶部布局指南会自动为您完成这部分,这是一个优势。
猜你喜欢
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 2012-05-30
相关资源
最近更新 更多