美文网首页
RDVTabBarController的一个布局bug

RDVTabBarController的一个布局bug

作者: iOS打怪升级 | 来源:发表于2018-05-30 19:58 被阅读18次
    描述,当在tabBar 隐藏(push 了控制器的)的状态下,设置selectIndex 就会页面布局异常

    解决办法:实现一个RootTabViewController的子类重写selectedIndex

     - (void)setSelectedIndex:(NSUInteger)selectedIndex{
    //修正containView的frame 
         [self setTabBarHidden:NO animated:NO];
         [super setSelectedIndex:selectedIndex];
    }
    
    
    源码分析
    • setSelectedIndex 内部实现会根据contentView 的bounds修改selectedViewController 的frame
    
    - (void)setSelectedIndex:(NSUInteger)selectedIndex {
        if (selectedIndex >= self.viewControllers.count) {
            return;
        }
        
        if ([self selectedViewController]) {
            [[self selectedViewController] willMoveToParentViewController:nil];
            [[[self selectedViewController] view] removeFromSuperview];
            [[self selectedViewController] removeFromParentViewController];
        }
        
        _selectedIndex = selectedIndex;
        [[self tabBar] setSelectedItem:[[self tabBar] items][selectedIndex]];
        
        [self setSelectedViewController:[[self viewControllers] objectAtIndex:selectedIndex]];
        [self addChildViewController:[self selectedViewController]];
    /**这里是关键,如果contentView 的bounds 异常那么selectedViewController就会异常了**/
        [[[self selectedViewController] view] setFrame:[[self contentView] bounds]];
        [[self contentView] addSubview:[[self selectedViewController] view]];
        [[self selectedViewController] didMoveToParentViewController:self];
        
        [self setNeedsStatusBarAppearanceUpdate];
    }
    
    • setTabBarHidden : animated: 内部会更新contentView 的frame
    - (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated {
        _tabBarHidden = hidden;
        
        __weak RDVTabBarController *weakSelf = self;
        
        void (^block)() = ^{
            CGSize viewSize = weakSelf.view.bounds.size;
            CGFloat tabBarStartingY = viewSize.height;
            CGFloat contentViewHeight = viewSize.height;
            CGFloat tabBarHeight = CGRectGetHeight([[weakSelf tabBar] frame]);
            
            if (!tabBarHeight) {
                tabBarHeight = 49;
            }
            
            if (!hidden) {
                tabBarStartingY = viewSize.height - tabBarHeight;
                if (![[weakSelf tabBar] isTranslucent]) {
                    contentViewHeight -= ([[weakSelf tabBar] minimumContentHeight] ?: tabBarHeight);
                }
                [[weakSelf tabBar] setHidden:NO];
            }
            
            [[weakSelf tabBar] setFrame:CGRectMake(0, tabBarStartingY, viewSize.width, tabBarHeight)];
    /**这里是关键**/
            [[weakSelf contentView] setFrame:CGRectMake(0, 0, viewSize.width, contentViewHeight)];
        };
        
        void (^completion)(BOOL) = ^(BOOL finished){
            if (hidden) {
                [[weakSelf tabBar] setHidden:YES];
            }
        };
        
        if (animated) {
            [UIView animateWithDuration:0.24 animations:block completion:completion];
        } else {
            block();
            completion(YES);
        }
    }
    

    场景说明: a是一个tab 下的根导航控制器 push 了 b ,此时tabBar 隐藏,现在点击b 上的按钮,通过set selectIndex 的方式跳转到 另外一个根控制器c ,问题发生了,因为在setSelected 方法在执行的时候,容器视图contentview 的高度是隐藏底部tabBar 的高度,可以简单理解成全屏高度,那么设置selectView 的frame 的时候就会高度不对,以为新的selectedView 是根控制器,根控制器显示的时候,tabBar 是需要显示的,frame 的高度应该是减去底部tabBar 的高度,但是此时的contentView 高度是全屏的高度,此时异常了

    **声明,这里的前提是认识在根控制器显示的时候,tabBar 应该隐藏,如果你不是这么理解的,那么上面的讨论就没意义了

    搭配隐藏显示tabBar 的代码如下:

    @interface HqUINavigationController:UINavigationController
    - (instancetype)initWithRootViewController:(UIViewController *)rootViewController;
    @end
    @implementation HqUINavigationController
    
    - (instancetype)initWithRootViewController:(UIViewController *)rootViewController{
        if (self = [super initWithRootViewController:rootViewController]) {
             rootViewController.navigationController.delegate = [HqNavigationDelegateHelper shareInstance];
        }
        return self;
    }
    @end
    
    
    @interface HqNavigationDelegateHelper()
    @end
    
    @implementation HqNavigationDelegateHelper
    + (instancetype)shareInstance{
        static dispatch_once_t token;
        static HqNavigationDelegateHelper * obj = nil;
        dispatch_once(&token, ^{
            obj = [[HqNavigationDelegateHelper alloc] init];
        });
        return obj;
    }
    
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
        if (navigationController.viewControllers.count > 1) {
            [viewController.rdv_tabBarController setTabBarHidden:YES animated:YES];
        }else
            [viewController.rdv_tabBarController setTabBarHidden:NO animated:YES];
    }
    
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
     
    }
    
    @end
    
    
    

    相关文章

      网友评论

          本文标题:RDVTabBarController的一个布局bug

          本文链接:https://www.haomeiwen.com/subject/glmxsftx.html