概述:
1、隐藏:系统方法隐藏;自定义容器随意隐藏
2、自定义:干掉tabBar 的view,并替换;完全自定义一,把pageViewController作为容器
在UITabbarController包含的UINavigationController应用中,如果UINavigationController某一页(某个level)需要隐藏Tabbar,之前的做法是在push那一页之前,将那一页的ViewController中的hidesBottombarWhenPushed参数设为YES,这样当那一页push进UINavigationController中时,底部的Tabbar就会隐藏掉。
但是这种方法有一个潜在的而又巨大的问题,假设现在我有3个ViewController A,B,C,其中A为Navigation的RootViewController,A中push B,B中push C。这时,如果我想要在B中隐藏Tabbar,而在C中显示Tabbar,根据最朴素的想法就是:
//SecondLevel即为B,此代码在A中进行
SecondLevelViewController *_2vc = [[SecondLevelViewController alloc]init];
_2vc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:_2vc animated:YES];
//ThirdLevel即为C,此代码在B中进行
ThirdLevelViewController *_3vc = [[ThirdLevelViewController alloc] init];
_3vc.hidesBottomBarWhenPushed = NO;
[self.navigationController pushViewController:_3vc animated:YES];
然而很可惜,虽然A中push B能让Tabbar隐藏,但是B中push C,就没办法让Tabbar显示出来了。这是一个比较郁闷的问题,我只能猜想其中的原理是,当设置某一层hidesBottomBarWhenPushed = YES之后,UITabbarController就像不存在一样,就连调用self.tabbarController或者self.navigationController.tabbarController也应该是nil。
所以解决办法只能是手动隐藏Tabbar。
- (void) hideTabBar:(UITabBarController *) tabbarcontroller {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, HEIGHTIPHONE, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, HEIGHTIPHONE)];
}
}
[UIView commitAnimations];
}
- (void) showTabBar:(UITabBarController *) tabbarcontroller {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, HEIGHTIPHONE-view.frame.size.height, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, HEIGHTIPHONE-49)];
}
}
[UIView commitAnimations];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (_isPush) {
[self showTabBar:self.tabBarController];
}
_isPush = NO;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self hideTabBar:self.tabBarController];
}
上面是在一篇文章里学到的,原文地址点击打开链接,很给力,给我门找到了一个平滑的方法,看着很流畅
1 、 在做显示动画的时候我建议写在viewDidAppear里面,这样看着舒服。
2、 两个方法分开,需要隐藏的视图光写隐藏就好了,
下面是我自己的一套实现思路,仅供参考
用一个UIPageViewController替代UITabBarViewController,把几个控制器放在Page里面,然后在pageVC下面放一个CollectionView来自定义我们下面Bar的样式。Demo就不写了,好好读一下,能更好的去自定义这些东西
1、PageViewController实现及属性、接口暴漏
.h文件:
@interface GPPageViewController : UIViewController
/** 当前页 */
@property (nonatomic, assign, readonly) NSInteger currentPageIndex;
/** 转场动画 默认yes */
@property (nonatomic, assign) BOOL animated;
/** 可否滚动 默认yes */
@property (nonatomic, assign) BOOL scrollEnabled;
// 实现pageVC的两个条件
/** 子控制器集合 */
@property (nonatomic, strong) NSMutableArray *viewControllers;
/** inset (默认全屏)*/
@property (nonatomic, assign) CGRect contentInset;
- (void)selectItemAtIndex:(NSInteger)index ;
- (void)pageDidChange:(NSInteger)page;
/** 滚动 */
@property (nonatomic, strong, readonly) UIScrollView *scrollView;
@end
.m文件
#import "GPPageViewController.h"
@interface GpPageViewController ()
/** 页面控制 */
@property (nonatomic, strong) UIPageViewController *pageViewController;
/** 页面 */
@property (nonatomic, strong) UIPageControl *pageControl;
@end
@implementation GPPageViewController
- (instancetype)init {
if (self = [super init]) {
CGSize mainSize = [UIScreen mainScreen].bounds.size;
self.contentInset = CGRectMake(0, 0, mainSize.width, mainSize.height);
self.scrollEnabled = YES;
self.animated = YES;
self.automaticallyAdjustsScrollViewInsets = NO;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
}
- (BOOL)shouldAutorotate {
return NO;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)backForward_default_navigation {
if (self.navigationController.topViewController == self &&
self.navigationController.viewControllers.count > 1) {
[self.navigationController popViewControllerAnimated:YES];
} else {
[self dismissViewControllerAnimated:YES completion:nil];
}
}
- (void)setScrollEnabled:(BOOL)scrollEnabled {
_scrollEnabled = scrollEnabled;
[self findScrollView];
}
- (void) setContentInset:(CGRect)contentInset {
_contentInset = contentInset;
self.pageViewController.view.frame = contentInset;
}
- (void)setViewControllers:(NSMutableArray *)viewControllers {
if (viewControllers.count > 0) {
_viewControllers = viewControllers;
[self configurePageViewController];
}
}
#pragma mark - >> public <<
//选择
- (void)selectItemAtIndex:(NSInteger)index {
if (index != self.currentPageIndex) {
[self selectViewControllerAtIndex:index];
}
[self pageDidChange:self.currentPageIndex];
}
- (void)pageDidChange:(NSInteger)page {
}
#pragma mark - >> pageControl <<
//取控制器和控制器序号
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index {
return (UIViewController *)[self.viewControllers objectAtIndex:index];
}
- (NSUInteger)indexOfViewController:(UIViewController *)viewController {
return [self.viewControllers indexOfObject:viewController];
}
#pragma mark - >> pageViewController <<
- (void)selectViewControllerAtIndex:(NSInteger)index {
if (index >= _viewControllers.count) {
index = _viewControllers.count - 1;
}
if (index < 0) {
index = 0;
}
UIViewController *startingViewController = (UIViewController *)[self viewControllerAtIndex:index];
NSArray *viewControllers = @[startingViewController];
if (index > self.currentPageIndex) {
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:self.animated completion:nil];
} else if (index < self.currentPageIndex) {
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:self.animated completion:nil];
}
_currentPageIndex = index;
}
- (void)configurePageViewController {
if (!_pageViewController) {
_pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
_pageViewController.delegate = self;
_pageViewController.dataSource = self;
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
_pageViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
_pageViewController.view.frame = _contentInset;
[_pageViewController didMoveToParentViewController:self];
UIViewController *startingViewController = (UIViewController *)[self viewControllerAtIndex:self.currentPageIndex];
NSArray *viewControllers = @[startingViewController];
[_pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
self.view.gestureRecognizers = _pageViewController.gestureRecognizers;
[self findScrollView];
}
#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:viewController];
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [self indexOfViewController:viewController];
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.viewControllers count]) {
return nil;
}
return [self viewControllerAtIndex:index];
}
#pragma mark - UIPageViewControllerDelegate
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation {
UIViewController *currentViewController = self.pageViewController.viewControllers[0];
NSArray *viewControllers = @[currentViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:self.animated completion:nil];
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMin;
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if (completed) {
_currentPageIndex = [self indexOfViewController:[pageViewController.viewControllers lastObject]];
// 子类如果实现了方法,会收到滚动消息
[self pageDidChange:self.currentPageIndex];
}
}
// 偷偷的找到滚动
- (void)findScrollView {
UIScrollView *scrollView;
for(id subview in self.pageViewController.view.subviews){
if([subview isKindOfClass:UIScrollView.class]){
scrollView = subview;
scrollView.delegate = self;
break;
}}
scrollView.scrollEnabled = self.scrollEnabled;
_scrollView = scrollView;
}
@end
上面是实现一个pageVC的代码
2、然后我们可以创建一控制器AVC,继承于上面的GPPageViewController,然后再给AVC自定义一个tabBarView就可以作为我们的TabBarVC了,下面们简单的写一下主要的代码
- (void)viewDidLoad {
[super viewDidLoad];
// 1、设置控制器的展示范围,还有控制器都有哪些,加上collectionView伪装成的tabBarView
//设置一下控制器的范围,
self.contentInset = CGRectMake(0, 0, 屏幕宽度, 屏幕高度 - TabBarHeight - iPhoneX的多余高度);
self.scrollEnabled = NO;
self.animated = NO;
self.viewControllers = @[vc1, vc2, vc3];
// 添加一个collection创建的View,模拟tabBar
/* 实现... */
}
//2、反向控制:page修改后,让collection刷新()
- (void)pageDidChange:(NSInteger)page; {
[_tabBarCollectionView reloadData]
}
//3、正向控制:tabBarCollectionView 控制page的当前选定页,也可以考虑使用block回调等
- (void)didSelectItemAtIndex:(NSInteger)index {
if (index != self.currentPageIndex) {
[self selectItemAtIndex:index];
} else {
// 可以像微信、京东一样,选定后再点击,就刷新一下当前页面
}
}
3、回归主题,我们讨论的是如何隐藏tabBar,具体如下
1)如果二级界面都需要隐藏,那么直接找到AVC的导航,去推二级界面,就OK了
2)如果需要部分二级别界面显示tabBar,那就在单个控制器的导航(AVC.viewControllers[index].navigationViewController)上推二级界面
其实tabbar是我们自定义的一个collectionView,那么想怎么玩,你自己随时拿过来搞就可以了,为了方便拿到这个TabBar,可以把AVC的初始化设置成单例,暴漏其tabBar就可以啦。也方便几个控制器之间用代码来回切换。
致歉:之前这篇文章属于转载的,存在一定的错误,由于时间问题也没来得及维护,今天翻看发现,存在一些问题,做了修改,同时还增加了一个自定义tabbar的方法,方便使用