CHNavBar1.2.1

CHNavBar1.2.1

测试测试过的
语言语言 Obj-CObjective C
许可证 MIT
发布最新发布2018年10月

WooWoo维护。




TLYShyNavBar banner

v1.0,终于!有了更好的代码设计和完整的功能!

Pod Version
Pod License
Carthage compatible

这个组件可以帮助您模仿您在Facebook、Instagram、9gag(就是使用这个的!)和其他应用中看到的导航栏自动滚动的效果。不仅如此,它还具备添加一个附加扩展,使其也能滚动的功能!它旨在设计得易于使用,并在我们自己的Telly应用[1]中进行过实战测试!

Battle Tested!!

[1]: AppStore版本未包含最新版本,即将推出。😁

[*]: 此处的内容仅用于展示如何在Telly应用中使用此组件,我们保留根据与索尼影业的合同展示这些内容的权利。

简介

特性

特性 演示
使用扩展视图滚动UINavigationBar
支持不透明和透明的UINavigationBar
功能齐全,带动画和可变阻力
反应灵敏、坚韧性且健壮
支持带有头部的UITableView
欢迎使用UICollectionView
通话时的状态栏?没问题!
粘性扩展视图(感谢@yukaliao!)
粘性导航栏(感谢@TiagoVeloso!)
熄灭整个导航栏(感谢@longsview!)

您可以在Objective-C演示中测试一些这些功能

快速入门

  1. 获取组件
  • 使用CocoaPods

    将以下内容添加到您的Podfile pod 'TLYShyNavBar'

    引入头文件#import <TLYShyNavBar/TLYShyNavBarManager.h>

  • 使用Carthage(感谢@bradleyayers!)

    将以下内容添加到您的Cartfile github "telly/TLYShyNavBar"

    引入头文件#import <TLYShyNavBar/TLYShyNavBar.h>

  • 使用子模块

    下载项目/git子模块,然后将TLYShyNavBar文件夹拖放到您的项目。

    导入头文件:#import "TLYShyNavBarManager.h"

  1. 只需一行代码即可开始使用!!
/* In your UIViewController viewDidLoad or after creating the scroll view. */
self.shyNavBarManager.scrollView = self.scrollView;

重要提示!!

  1. 不要与UITableViewController一起使用。请将UITableView添加为UIViewController的子视图。
  2. 如果您正在将代理分配到您的scrollView,请先这样做,然后再将scrollView分配给TLYShyNavBarManager!有关更多信息,请参阅下面

在Swift中使用TLYShyNavBar

实际上不需要做任何特别的事情。只需确保您已设置桥接头,并导入

#import "TLYShyNavBarManager.h"

然后,您应该可以遵循Objective-C的说明,因为代码几乎是相同的。

设计目标

  • 易用性:这是最重要的,绝不能妥协。即使兼容性中断或多功能性有限,该组件也应易于集成。
  • 可移植性:更少的依赖,轻量级,自包含,……等等。
  • 兼容性:尽可能使组件简单地在您抛给它的情况下工作。

深入了解

上面的示例虽然小,但却是完整的!它使得导航栏充满了谦卑,当滚动视图开始滚动时,它就会开始让路。但,您可能想做的不仅仅是这些!

访问害羞的管理器

您只需在您的UIViewController子类内部作为属性访问它。该属性为您进行了懒加载,因此您无需实例化任何内容。

self.shyNavBarManager

添加扩展视图

您可以为它分配自己的扩展视图,并且它将直接出现在导航栏下方。它会在导航栏开始收缩之前滑到导航栏下方。添加扩展视图就像这样简单

/* Also in your UIViewController subclass */
[self.shyNavBarManager setExtensionView:self.toolbar];

将扩展视图粘附到顶部,并使其在导航栏隐藏时保持可见

/* Also in your UIViewController subclass */
[self.shyNavBarManager setStickyExtensionView:YES];

控制阻力

当您开始向上滚动(向下移动视图)或向下滚动(向上移动视图)时,您可能希望导航栏在改变状态之前等待一段时间(容忍度)。(例如,如果用户向下滚动10 px,不要立即开始显示收缩的导航栏,而要等到他滚动100 px左右)。

您可以使用以下属性在shyNavBarManager上控制。

/* Control the resistance when scrolling up/down before the navbar 
 * expands/contracts again.
 */
@property (nonatomic) CGFloat expansionResistance;      // default 200
@property (nonatomic) CGFloat contractionResistance;    // default 0

控制淡入淡出行为

您可以通过此属性自定义UINavigationBar的淡入淡出行为

/* Choose how the navbar fades as it contracts/expands.
 * Defaults to FadeSubviews
 */
@property (nonatomic) TLYShyNavBarFade fadeBehavior;

如何工作

好吧,我要承认我添加这个部分纯粹是为了发泄我对这个项目是如何结合在一起以及背后的决策过程的感慨。

基础

在一个组件用户层面上,这是通过向UIViewController添加一个具有TLYShyNavBarManager属性的分类来实现的。该属性进行了懒加载,以减少不必要的开销,并降低入门门槛。从该属性开始,您可以开始为该视图控制器自定义TLYShyNavBarManager

现在,您可能开始询问,导航栏呢?嗯,导航栏是通过您使用的视图控制器访问的。让我们来分析一下...

  1. 当您第一次访问shyNavBarManager时,它会用传递给它的self参数创建,事实上将shyNavBarManager绑定到了UIViewController
  2. shyNavBarManager通过分配的UIViewController访问UINavigationBar

……这就是基本设置的方式!

扩展视图

当您调用setExtensionView:时,它只是调整了一个内部容器视图的尺寸,并将您的扩展视图添加到其中。这里没有魔法,只是简单的单个视图扩展。

捕获滚动视图事件

这个真的很痛苦……首先,这个项目经历的实验包括

  • 观察contentOffset属性
  • 将自己设置为UIGestureRecognizer的目标
  • UIPanGestureRecognizer添加到滚动视图中。
  • 让用户实现UIScrollViewDelegate,并给我们发送事件。

上述方法除了最后一点之外,并没有带来我们期望的完美体验。然而,这确实导致了代码冗余,并迫使组件用户实现UIScrollViewDelegate。这就是NSProxy发生的时候了。

当您将scrollView属性分配给TLYShyNavBarManager时,我们将在UIScrollView上附加一个代理对象作为代理,并将原始代理添加到该代理。代理对象将我们感兴趣的事件转发到TLYShyNavBarManager,当然,对于原始选择器,它将执行所有其他正常操作,您甚至不会注意到任何不同!

抽屉概念

通过优雅的双向链表实现将偏移量应用于导航栏和扩展视图。我们将偏移量设置到第一个节点(导航栏),然后...

  • 如果在收缩状态

    • 我们将收缩量传递给下一个节点,并返回残留量。
  • 如果我们在扩展

    • 我们处理第一个节点的偏移量,并将残留量传递给下一个节点。

这是一个简单概念。比如说,当navbar收缩时,我们向下拖动100 px。navbar将占用44 px来扩展,然后将剩余的56 px传递给下一个节点(扩展视图)以计算其偏移量。收缩时也如此,但它是从最后一个节点开始,一路向上到导航栏。

我们还添加了一个父子关系,用于单一目的:使子节点遵循其父节点的偏移。因此,如果父节点(例如,navbar)向顶部滚动,我们确保在计算中调整父节点的偏移量,以便看起来子节点是父节点的子视图。

注意:尽管可能有一种视图正在扩展和收缩的错觉,但实际上这只是视图的平移(滚动)。真正调整边界可能会有优势,例如,这样扩展视图就不会出现在导航栏后面,因此将来可能会探索这种方法。

常见问题解答

透明navbar在向上滚动时显示黑色条带

您必须检查视图控制器配置中的“扩展边缘”下的“不透明导航栏”。这个解决方案的归功于@tiois

我收到一个异常,指示:“请确保viewController已经附加到导航控制器”

使这个组件如此易于使用是有劣势的。如果您仔细阅读了如何工作的部分,您就会意识到在它被包含在UINavigationController层次结构之前尝试配置shyNavBarManager将破坏组件,因为在该组件内部,我们找不到导航栏,并将触发断言

NSAssert(navbar != nil, @"Please make sure the viewController is already attached to a navigation controller.");

当然,可以通过创建自己的TLYShyNavBarManager来避免这种情况,如下所示

TLYShyNavBarManager *shyManager = [TLYShyNavBarManager new];
shyManager.expansionResistance = 777.f;

/* ... sometime after the view controller is added to the hierarchy  */
viewController.shyNavBarManager = shyManager;

贡献

欢迎Pull Requests!尽管如此,测试更改很重要。只需浏览演示,确保一切正常。请确保检查透明和不透明模式。一旦所有都很好,您就可以开始了!

如果是功能或缺陷,如果能在示例项目中添加一个新视图来展示此缺陷/功能,将会非常感激。

感谢所有创建问题、给我发邮件或提交Pull Requests的人。特别感谢提交了被合并的代码的人。这个项目是在您的帮助下才得以实现的。(查看贡献者图表

作者

Mazyod (@Mazyod)

类似项目