最近想要自定义一个tabbarController
,本篇文章是为了解下原生的工作原理,参考来源为Developer Documtation
和控制台调试。所以下面的思路
含有推测部分,只能表示笔者的思路。如有错误,请指正。如能告知在哪了解原生控件工作原理,万分感激!!!
1. 使用
- 指定管理的子控制器
viewControllers
,同时可以通过selectedViewController
或selectedIndex
指定默认选中的控制器 - 对于
tabbar
上的标签控制则通过子控制器的tabbarItem
实现。tabBarController
上的tabBar
属性(只读)不能直接修改。 - 通过
UITabBarControllerDelegate
协议控制或添加交互行为。该协议可选。
注意:tabbar
最多能显示5个item,超过会将第5个item变为More
。点击More
再选择其他。
2. 思路
tabbarController
继承于UIViewController
,子控制器视图和tabbar
都是添加到该UIViewController
的view
上。切换时将原来的子控制器视图移除,将新的视图添加。
对于More
项,猜测:检测到控制器数大于5时,新建一个数组存储前4项控制器和moreNaviController
,多出的控制器则赋值给。moreNaviController
的viewControllers
创建moreNaviController
同时会创建一个UIMoreListController
用于列出多出的控制器。但是控制台调试时,点击More
时,moreNaviController
的viewControllers
只包含列表控制器。当选择多出的控制器时,viewControllers
也只包含了列表控制器和选中的控制器。
也即是在多出的控制器间切换时,更新的是viewControllers
属性,而不是push pop
。我的猜想:由于导航控制器时以栈的形式管理的,如果一次性将控制器加到viewControllers
。当根控制器UIMoreListController
依次push
了5,6,7,此时要从7回到5,会有多余的入栈出栈行为。
而通过直接更新viewControllers
,也就是直接替换了导航栈,能可直接刷新视图到viewControllers
的最后一个控制器的视图。
所以moreNaviController
的viewControllers
是 ?动态? 调整的。
3. 属性
属性 | 作用 |
---|---|
tabBar | 只读属性,仅为用于-[UIActionSheet showFromTabBar:]方法 |
viewControllers | 子控制器 |
customizableViewControllers | 当出现More时,可以对各控制器顺序重新布置,该属性指定哪些控制器能被重新布置,其他的则不能 |
moreNavigationController | More标签,只读属性。通过该属性可以拿到多出的子控制器 |
selectedViewController | 当前选中的控制器,可以修改替换成其他的,包括More |
selectedIndex | 选中的控制器的索引,从左至右从0开始,值和viewControllers的索引相同,修改该属性也可以切换。但是不能选中More |
4. 协议UITabBarControllerDelegate
- 指定选中的控制器
- 选中后执行方法
// 是否切换到用户选中的viewController
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;
// 切换后
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
- 自定义控制器顺序前(后)要做的事
// 自定排序窗口显示前
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers;
// 排序窗口退出前
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed;
// 结束排序后(tvOS不可用)
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed;
-
tabbar
横竖屏支持
- (UIInterfaceOrientationMask)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController;
- (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController;
- 动画
- (nullable id <UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController
interactionControllerForAnimationController: (id <UIViewControllerAnimatedTransitioning>)animationController;
// contentController的切换动画
- (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);