无限标签栏

最近,我被要求从我们的一个应用程序中删除一个较旧的框架,并用更新的(兼容iPhone X的)替代品替换它。 当我开始创建替代产品时,我们公司将计划转移到其他方面,但是我不想失去项目最后几周的工作/更新,以使所有工作顺利进行。 这就是为什么我将向您展示我本周工作的绝妙内容! (已完成的Repo Link在底部!)

好的,所以首先创建一个单视图应用程序(对于我的演示,我将其命名为新的标签栏)。 您要在主视图控制器中添加一个collectionview和一个Container View。 我将容器视图设置为将尾随,前导和顶部与安全区域对齐,并将展位空间与集合视图对齐。 我的收藏夹视图约束设置为:高度60,将尾随,前导和底部对齐到安全区域,顶部空间对齐到容器视图。 继续并删除设置Container View Controller时获得的defualt view controller。 在您的collectionView单元格中添加一个imageView和一个标签。 将图像视图的约束设置为:到单元格的尾随空间和前导空间10(消除了一个名为tabCell的类),顶部空间等于单元格,底部空间至标签。 将标签约束设置为:尾随前导底部到单元格,高度为15,顶部到imageView。 然后选择您的collectionView并将“滚动方向”设置为“水平”。 并且您的单元格大小为60X60。 将重用标识符设置为“ tabCell”

然后将您的Outlets设置到ViewController(我的名为MainViewController),并在viewDidLoad中设置您的collectionView委托和dataSource。 创建对MainViewController的扩展,以熟悉协议。 现在在DataSource中,只需为numberOfItemsInSection返回1并在cellForItemAtIndex中返回UICollectionViewCell()。 创建一个名为TabCollectionViewCell的新类,并通过联播为您的标签单元分配该类。 为imageView和Label设置插座。 完成后,它应该看起来像这样(请注意,我的标签渲染图未显示,因此我将其突出显示。):

现在我们都准备开始编程了!!

我个人想先解决最小的问题,所以我将设置TabCollectionViewCell。 覆盖您的awakeFromNib并准备调用名为updateWithImage的函数的prepareForReuse。 您的updateWithImage应该包含一个可选图像,并将该图像设置为tabImageView.image属性。 如果没有传递任何内容,则将其设置为nil。

由于我们正在使用自定义选项卡,因此我创建了一个选项卡模型(因为我很有创造力,因此命名为选项卡!)我将类Tab设置为具有tabName:String和tabImageName:String,并设置init来保存这些新值。

是时候进入我们的MainViewController了。 设置一个私有Tab变量,并使其成为Tab列表,一个私有selectedIndex来保存我们的索引选择。 并在didLoad视图中将selectedIndex设置为0。同样在viewDidLoad中,在设置collectionViewDelegate和Datasource之前,向选项卡列表调用一个新函数addingTabs。 在您的addTabs函数中设置您的主选项卡,然后设置一些选项卡(请注意,在我的项目中,我将其主题设置为超级护林员,并添加了一些经典以及较新的超级护林之一。

将您的numberOfItemsInSection更新为tabs.count,并更新cellForItemAt indexPath以返回tabCell(确保将collectionView.dequeueReusableCell(withReuseIdentifier:“ tabCell”,用于indexPath)用作TabCell)。 由于将所选索引的颜色设置为彩色更好,因此我们应该在此处进行设置。 我将选定的“索引”标签设置为蓝色,没有选定的标签为黑色。 在您的Delegate扩展中,创建didSelectItemAt indexPath并将您的selectedIndex设置为indexPath.row。

返回到您的selectedIndex声明,并向其添加didSet,以调用新函数setViewController()。 在setViewController(私有函数)中,我们将处理将容器视图更新为所选视图控制器的操作。 首先创建一个var viewController = UIViewController(),这将是我们viewController的占位符以及我们将更新的所有值。 然后打开带有默认显示UIViewController的selectedIndex。 我将所有视图控制器都放在导航控制器中,因此可以设置标题和navigationItem按钮。 现在,您可能会问我们将如何跟上视图控制器的发展,为此,我有一个很棒的答案,我已经引用了几次。 创建一个私有var activeViewController:UIViewController并添加didSet到removeInactiveViewController(inactiveViewController:oldValue)和updateActiveViewController()。 因为我没有提出这些功能,所以我将它们放在这里,让您阅读它们的工作原理,因为它们实在太棒了:

 私有函数removeInactiveViewController(inactiveViewController:UIViewController?){如果让inActiveVC = inactiveViewController {inActiveVC.willMove(toParentViewController:nil)inActiveVC.view.removeFromSuperview()inActiveVC.removeFromParentViewController()}}私有函数updateActiveViewController(){如果让activeVC = activeView addChildViewController(activeVC)activeVC.view.frame = containerView.bounds containerView.addSubview(activeVC.view)activeVC.didMove(toParentViewController:self)}} 

现在回到我们的setViewController中,以viewController为根将您的activeViewController设置为navigationController。

现在,我们将从MainViewController稍事休息,开始使用一些基本的ViewController和我们的家庭View Controller。 因为我首先喜欢简单的东西,所以我们将从基本的视图控制器开始。 通过情节提要或xibs创建一些ViewController,然后在viewDidLoad中将背景色设置为不同的颜色。 我添加了一个imageview和一个标签,并将它们放在我的视图控制器上的不同位置,以防万一有人遇到颜色问题。 这些视图/标签将成为我们在MainViewController中设置的标签信息,以及为什么需要占位符viewController属性。 现在已经完成了,让我们开始使用我们的HomeViewController。

我创建了一个名为Home的新情节提要,并将初始视图设置为标准的View Controller。 我在表视图中添加了一个自定义单元,并使用了reuseIdentifier“ HomeTabCell”。 我创建了一个名为HomeTabCell的类:UITableViewCell,并向该单元格添加了一个imageView和一个标签。 在HomeViewController.swift中,我为表格视图创建了出口,设置了一个新的私有var [Tab]()并创建了一个不同的addTabs函数,因为也许我想让自己的单元格不同于集合视图,或者想要更多的单元格来代替特殊的集合视图。原因。 在viewDidLoad中,设置tableView数据源,并委派并创建扩展。 在行的单元格中创建tabCells,并在numberOfRowsInSection中返回tabs.count。

现在是有趣的部分。 选择tableView单元格时,如何选择集合视图单元格并更新视图控制器? 好吧,代表团将是答案! 在MainViewController类的顶部,创建一个协议DidSelectTabFromTableDelegate:class。 在其中设置一个包含IndexPath的功能! (名为func scroll(指向索引:IndexPath!))。 在您的主视图控制器中,创建一个代表的弱变量,然后在didSelectRowAt的indexview的tableviewDelegate中,包含您的proxy.scroll(to:indexPath)。

回到mainViewController中,在setViewController中将默认情况设置为homeViewController并设置tabSelectDelegate = self。 创建该协议的扩展名,并在函数中确保将索引偏移1,以说明您的homecollectview选项卡不应位于hometableview单元格中。 如果您拥有超过tabs.count的数量,也可以相应地进行处理。 由于我们想要选择的某种视觉表示,所以我有collectionView.scrollToItem(at:indexOffset,at:.right,animation:true)。 完成后请确保reloadData。

最终结果:

回购:https://github.com/EricADockery/infiniteTabBar

注意:如果您每次选择一个集合视图单元时都不需要新的视图实例,那么我将建立一个模型来保持过渡状态并相应地加载这些视图。 另外,由于我只是从互联网上获取了随机的电力护林员图像,因此您可能不需要在仓库中调整大小图像功能。