iOS tabBarView的隐藏以及自定义tabBarViewController

概述:

1、隐藏:系统方法隐藏;自定义容器随意隐藏

2、自定义:干掉tabBar 的view,并替换;完全自定义一,把pageViewController作为容器

 

第一种需求,需要二级界面隐藏tabBar,三级界面再显示出来(很奇葩的需求)

在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、 两个方法分开,需要隐藏的视图光写隐藏就好了,

 

第二种需求,二级界面都隐藏,TabBar样式可自定义(颜色、图标,甚至tabBar的高度)

下面是我自己的一套实现思路,仅供参考

用一个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的方法,方便使用

你可能感兴趣的:(iOS,iOS,UI控件的使用,ios,tabBar)