创建一个UITabBarController框架

导航(如果不是)是任何应用程序中最重要的方面之一。 选择用户如何在不同的屏幕之间导航对于您的应用程序成功至关重要。

随着AppStore的兴起,人们非常清楚什么是最受欢迎的导航方式。 汉堡菜单,滑动菜单,侧边栏,无论您想称呼它们如何。 这种导航形式成为应用程序的代名词。 我个人发现补充工具栏有很多缺陷。 但是由于我不是UX设计人员,因此您可以在本文中阅读更多有关面向设计的评论。

正如您可能从这篇文章的标题中得出的那样,我最喜欢的应用程序导航形式是UITabBar。 如果我们看一下心爱的Apple的大多数应用程序,则在大多数应用程序中都普遍使用UITabBar。 App Store,手表,时钟和音乐-都使用UITabBar进行导航。 要了解有关使用它的UX好处的更多信息,请查看此文章。

为什么要创建框架?

UITabBar已经非常容易在Swift中使用UIKit实现。 那么创建整个框架有什么需要? 标准的UITabBar对我来说有点无聊,我想为组件增加更多个性。 另外,最好创建一些可重用的东西,无需更改太多代码即可对其进行样式设置和动画处理。

在本文中,我不会介绍创建CocoaTouch框架所需的步骤。 要开始创建可重用的框架,请阅读Alec O’Connor的这篇很棒的文章,我将其用作参考。

既然我们已经讨论了为什么要建立一个框架并列出我们想要实现的目标,那么让我们开始CODE😎! 我们希望我们的框架遵守一些原则和概念。

原理与概念

  • 固体
  • 面向协议

先决条件

作为先驱,我建议您熟悉以下原则:

  • 访问修饰符
  • 数据源和委托
  • 程序限制

这些是设计和开发框架架构时应牢记的核心原则。 当我们在代码中遇到它时,我将进一步扩展每个概念。

至此,您已经为框架项目创建了一个很酷的名称,例如MDVTabBarController。 首先,一些小组结构👷‍♀️。

TabBarController基本上是三种类型的组件的组合。 它们是:代表每个选项卡的TabBarItems,容纳项的TabBar,最后是一个顾名思义的TabBarController,它控制上述组件。 我们将从最小的组件开始,然后从那里构建我们的框架。 最后,我们希望有一个框架来利用插件动画。

MDVTabBarItem

创建一个名为MDVTabBarItemable的文件将其放置在“ 协议”组中,然后创建一个名为MDVTabBarItem的文件,并将其放置在MDVTabBar组中。

MDVTabBarItemable是我们希望所有TabBarItem都遵守的协议。 我们将用UIView替换标准的UITabBar和UITabBarItem,因为我相信它将提供更大的灵活性。 该协议定义了两个方法configure ,用于设置TabBarItemsetState。 最后一个将TabBarItem设置为选中或未选中。 类型别名 MDVTabBarContainer定义了动画师要使用的接口。

MDVTabBarItem接收带有图像的UITabBar项,并创建一个以图像为中心的UIView。 目前,MDVTabBarItem将不处理标题标签,但是可以通过创建UILabel并将其放置在UIView中来轻松添加。 您会注意到尚未执行所需的初始化 。 这是情节提要用于初始化组件的初始化程序。 我们将不会使用情节提要,因此无需实施。

MDVTabBar

MDVTabBar是一个非常复杂的类,因此我们将在各节中进行介绍。 首先,让我们看一下属性和初始化。 创建一个名为MDVTabBar的文件,并将其放置在MDVTabBar组中。

MDVTaBarDelegateMDVTabBarDataSource 是我们稍后会定义的协议。 创建可重用框架时,请始终牢记可访问性修饰符。 首先,让变量尽可能私有。 如果需要在其定义类之外修改变量,请在类内部创建一个公共设置方法来处理修改。 在Swift中,private(set)使我们能够保持属性私有,同时具有内部范围获取器。

动画师

动画师已经介绍过,因此让我们深入研究实现。 创建一个名为MDVTabBarAnimatable的文件 将其放在协议组中。

我们有两种方法:

  1. prepareForAnimation —在初始化TabBar时调用此方法。 它为TabBar所需的样式或动画放置了所有必要的组件。
  2. performAnimation —当用户点击TabBar上的按钮时调用。 它执行从一个索引到下一个索引的动画。

该协议定义了所有动画师都应遵循的接口。 任何人都可以通过相应地实现此协议来创建一个动画师。 这意味着我们的框架可以轻松扩展以支持更多的动画,而无需对代码进行任何更改。

在面向对象的程序设计中, 开放/封闭原则指出“ 软件实体(类,模块,功能等)应开放以进行扩展,而封闭以进行修改 ”; 也就是说,这样的实体可以允许其行为扩展而无需修改其源代码。 (参考)

MDVTabBarDataSource + Delegate

创建一个文件名MDVTabBarDataSource + Delegate 并将其放在协议组中。

现在,我们将返回MDVTabBar并完成该类的实现。 从委托和数据源didSet方法开始。

每当设置我们的数据源时 ,我们都要进行配置。 这可能是由于动画师的更改或tabBarItems由于某些原因而更改的。 每当设置委托时,我们还希望将图标状态设置为初始状态。 这将使我们的TabBar处于正确的状态,并选择初始索引。 现在,让我们实现MDVTabBar缺少的方法。

  1. configure —确保我们的DataSource不为nil,在这种情况下这应该是不可能的。 然后,我们从提供的数据源中设置tabBarItems和动画师。
  2. createContainerRects —此方法负责为每个tabBarItem创建框架。
  3. createTabBarItemContainerRect —然后将在createContainerRects中创建的框架传递给此方法以创建UIView,该UIView将用作tabBarItem的容器/容器视图的目的。
  4. createTabBarItems —接下来,我们使用上述containerRects创建MDVTabBarItems。
  5. touchUpInsideForTabBarButton —现在,我们需要为每个tabBarButton触摸事件。 所有的tabBarButtons都调用相同的方法,但是我们使用它的标签来识别正在点击的按钮。
  6. changeIconState —最后,我们需要一种在图标的选定状态和默认状态之间切换的方法。

所有这些方法共同创建一个UITabBarItem,对其进行定位并为其提供选择器。 每种方法最多只能尝试执行一个工作单元。

单一责任原则是一种计算机编程原则,它指出每个模块或类都应对软件提供的功能的一部分负责,并且责任应由类完全封装。(参考)

MDVTabBarController

该课程也涉及到很多内容,因此我们将分部分研究它的创建。 因此,创建文件名MDVTabBarController并将其放置在MDVTabBar组中。

我想相信,除了我们尚未定义的DataSource和Delegate之外,这里没有其他与众不同的地方。 请注意该类已声明为open

我们仅使用两种方法来创建tabBarController。

  1. configureViews —我们打开数据源。 隐藏标准的tabBar,因为我们将其放置在该位置。 从dataSource设置viewControllers。 初始化MDVTabBar并使用约束进行设置。 最后,我们将tabBarController设置为MDVTabbar的委托和数据源。
  2. setupTabBarConstraints —我们使用约束来布局tabBar。

现在回到mdvTabBarControllerDataSource并实现didSet方法,如下所示:

  didSet {self.configureViews()} 

实现MDVTabBarDelegate和MDVTabBarDataSource

MDVTabBarControllerDataSource + Delegate

创建文件名MDVTabBarControllerDataSource + Delegate 并将其放在协议组中。

这些是我们想作为任何人实现我们的框架的API方法公开的方法。 由于MDVTabBarController已打开,因此可以将其子类化。 该类将充当委托和数据源,实现这些方法。 让我们细分一下如何使用这些方法。

  1. tabBarControllerInitialIndex —用于设置tabBar的初始索引。
  2. tabBarControllerViewControllers —为tabBar提供viewControllers。
  3. tabBarHeight —为tabBar提供所需的高度。 是! 我们可以使tabBar比标准UIKit小或高一个。 不要发疯,请始终遵循Apple的HIG。
  4. tabBarBackgroundColor —用于设置tabBar的背景色
  5. tabBarAnimator —提供要用于动画的Animator
  6. didSelectIndex —这是一个委托方法,当选择tabBarItem时将调用它。 选择选项卡时,可以使用此方法执行自定义操作。 例如,打开共享表或在使用相机触发权限的视图上。

MDVTabbableViewController

在先前的方法中,数字2使用MDVTabbableViewController ,这是我们尚未定义的类。 该课程肯定赢得了最具创意名称😅的奖项。 创建一个名为MDVTabbableViewController的文件,并将其放在“ 协议”组中。 这是我们的最终协议和课程。

协议和类型别名的这种组合用作TabBarControllerDataSource的保镖。 这将确保要在我们的tabBarController上显示的任何viewController应该提供一个tabBarItem,否则它将不会编译。

最后,我们完成了我们的框架! 剩下要做的就是创建一个项目,我们将在其中使用它并实现一个很酷的动画。 为了不延长本文的发布时间,我将提供指向Github的链接,并提供一个如何使用框架的示例。

我们建立了一个tabBarController,它具有即插即用的动画和样式。 我不会说框架是完整的。 该项目距离为已经像ESTabBarControllerRAMAnimatedTabBarController这样的tabBarController库提供完整解决方案还有很长的路要走。

我鼓励您检查回购,或者分叉它并创建自己的动画😀。 看到你们中的一些人会想到的是很有趣的。 在接下来的几周中,我将在本文开头发布更多类似动画的示例,以及如何实现这些示例。

感谢您的阅读,我期待您的反馈和对该框架的贡献。

  • ESTabBarController
  • RAMAnimatedTabBarController
  • 如何创建自定义标签栏