TLYShyNavBar 1.1.1

TLYShyNavBar 1.1.1

测试已测试
语言语言 Obj-CObjective C
LICENSE MIT
发布最新版本2016年10月

mazyod维护。




  • 作者
  • Mazyad Alabduljaleel

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

这个组件可以帮助您模仿在Facebook、Instagram、9gag(使用了此组件!)以及其他应用程序中看到的导航栏自动滚动。不仅如此,还具备了添加一个同时滚动的额外扩展功能!它设计用于易于使用,并且在我们的Telly应用程序[1]中进行了实战测试!

Battle Tested!!

[1]: AppStore版本尚未更新。敬请期待。😁
[*]: 展示的内容仅为演示Telly应用中使用该组件的方式,我们保留根据与索尼电影公司的合同展示这些内容的权利。

概要

特性

特性 演示
使用扩展视图滚动UINavigationBar
支持半透明和非透明UINavigationBar
完全功能,带动画和可变阻力
响应、灵活且健壮
支持UITableView,包括头部
UICollectionView也受到欢迎
呼叫状态栏?没有问题!
粘贴扩展视图(感谢@yukaliao!)
粘贴导航栏(感谢@TiagoVeloso!)
淡入整个导航栏(感谢@longsview!)

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

快速入门

  1. 获取组件

    • 使用CocoaPods
      将以下内容添加到您Podfilepod 'TLYShyNavBar'
      导入头文件 #import <TLYShyNavBar/TLYShyNavBarManager.h>

    • 使用 Carthage(感谢 @bradleyayers!)
      在您的 Cartfile 中添加以下内容 github "telly/TLYShyNavBar"
      导入头文件 #import <TLYShyNavBar/TLYShyNavBar.h>

    • 使用子模块
      下载项目/git 子模块,并将 TLYShyNavBar 文件夹拖到您的项目中。
      导入头文件 #import "TLYShyNavBarManager.h"

  2. 编写一行代码开始使用!!

/* In your UIViewController viewDidLoad or after creating the scroll view. */
self.shyNavBarManager.scrollView = self.scrollView;

重要提示!!

  1. 不要与 UITableViewController 一起使用。请将其 UITableView 添加为 UIViewController 的子视图。
  2. 如果您需要将代理分配给您的滚动视图,请在将滚动视图分配给 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 像素,不要立即开始显示收缩的导航栏,而是等待他滚动大约 100 像素)。

您可以使用 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属性
  • 将self作为UIGestureRecognizer的目标
  • 向滚动视图添加UIPanGestureRecognizer
  • 让用户实现UIScrollViewDelegate,并向我们发送事件。

上面的方法并未带来我们期待的理想体验,除了最后一个。不过,它确实在各个地方产生了冗余代码,并迫使组件用户实现UIScrollViewDelegate。这就是NSProxy出现的时候。

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

抽屉概念

通过对导航栏和扩展视图应用偏移量,我们通过优雅的二元链表实现方式。我们设置第一个节点(导航栏)的偏移量,并且...

  • 如果我们正在缩短

    • 我们将缩短量传递到下一个节点,它返回一个剩余量。
  • 如果我们正在扩展

    • 我们处理第一个节点的偏移量,并将剩余量传递到下一个节点。

这是一个简单的概念。比如说,我们在导航栏收缩的时候拖动了100 px。导航栏会用去44 px来扩展,然后将剩余的56 px传递给下一个节点(扩展视图)来计算其偏移量。对于收缩,也是一样,但它是从最后一个节点开始的,一直到导航栏。

我们还添加了一个父子关系,目的只有一个:让子元素跟随其父元素的偏移量。所以,如果父元素(例如导航栏)正在向上滚动,我们确保子元素在计算中适应父元素的偏移量,因此看起来像子元素是父元素的一个子视图。

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

常见问题解答

半透明导航栏在向上滚动时显示黑色条

您需要检查视图控制器配置中的“扩展边缘”下的半透明条。这个解决方案归功于@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;

贡献

欢迎提交PR(Pull Requests)!但是,测试更改同样重要。只需运行演示版即可,确保没有出错。请注意检查透明和不透明模式。一旦一切顺利,就可以提交了!

如果是功能或bug,我们非常感谢您在演示项目中添加新的视图来展示bug/功能。

感谢每一位提出问题、发送电子邮件和提交PR的人。特别感谢提交了已检查进来的代码的人!这个项目是在您的帮助下得以实现的。(查看贡献者图表

作者

Mazyod (@Mazyod)

类似项目