美文网首页iOS开发札记ios 界面处理
iPhone X push操作后tabBar偏移问题

iPhone X push操作后tabBar偏移问题

作者: timelyRain | 来源:发表于2017-11-24 16:02 被阅读1610次

    前言

    在iPhone X设备带有tabBar的页面,如果控制器的hidesBottomBarWhenPushed属性为YES,进行push操作之后,便会出现如下的一些问题,于是我查看了一次苹果系统的一些应用,发现它们是不隐藏tabBar的,估计是苹果就是不希望我们去隐藏它的tabBar。

    demo下载

    点击下载demo源代码

    问题描述:

    1、iPhone X push后,tabBar偏移

    异常显示效果:

    直接push.png
    2、iPhone X modal并返回之后, 再push后,tabBar偏移

    在带有tabBar的页面,模态弹出(presentViewController)并返回后,再任意执行push操作,便会出现如下异常
    异常显示效果:


    modal后push.png

    解决问题:

    1、自定义的BaseTabBar

    创建自定义的BaseTabBar,继承自UITabBar,替换TabBarController的tabBar,代码如下:

    
    YUBaseTabBar *baseTabBar = [[YUBaseTabBar alloc] init];
    [self setValue:baseTabBar forKey:@"tabBar"];
    
    
    2、重写tabBar的一些方法
    OC代码
    
    #import "YUBaseTabBar.h"
    
    @implementation YUBaseTabBar
    {
       UIEdgeInsets _oldSafeAreaInsets;
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
       self = [super initWithFrame:frame];
       if (self) {
           _oldSafeAreaInsets = UIEdgeInsetsZero;
       }
       return self;
    }
    
    - (void)awakeFromNib {
       [super awakeFromNib];
       
       _oldSafeAreaInsets = UIEdgeInsetsZero;
    }
    
    - (void)safeAreaInsetsDidChange {
       [super safeAreaInsetsDidChange];
       
       if (!UIEdgeInsetsEqualToEdgeInsets(_oldSafeAreaInsets, self.safeAreaInsets)) {
           [self invalidateIntrinsicContentSize];
           
           if (self.superview) {
               [self.superview setNeedsLayout];
               [self.superview layoutSubviews];
           }
       }
    }
    
    - (CGSize)sizeThatFits:(CGSize)size {
       size = [super sizeThatFits:size];
       
       if (@available(iOS 11.0, *)) {
           float bottomInset = self.safeAreaInsets.bottom;
           if (bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90)) {
               size.height += bottomInset;
           }
       }
       
       return size;
    }
    
    
    - (void)setFrame:(CGRect)frame {
       if (self.superview) {
           if (frame.origin.y + frame.size.height != self.superview.frame.size.height) {
               frame.origin.y = self.superview.frame.size.height - frame.size.height;
           }
       }
       [super setFrame:frame];
    }
    
    @end
    
    
    swift代码
    class YUBaseTabBar: UITabBar {
    
    var oldSafeAreaInsets = UIEdgeInsets.zero
    
    @available(iOS 11.0, *)
    override func safeAreaInsetsDidChange() {
       super.safeAreaInsetsDidChange()
    
       if oldSafeAreaInsets != safeAreaInsets {
           oldSafeAreaInsets = safeAreaInsets
    
           invalidateIntrinsicContentSize()
           superview?.setNeedsLayout()
           superview?.layoutSubviews()
       }
    }
    
    override func sizeThatFits(_ size: CGSize) -> CGSize {
       var size = super.sizeThatFits(size)
       if #available(iOS 11.0, *) {
           let bottomInset = safeAreaInsets.bottom
           if bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {
               size.height += bottomInset
           }
       }
       return size
    }
    
    override var frame: CGRect {
       get {
           return super.frame
       }
       set {
           var tmp = newValue
           if let superview = superview, tmp.maxY != 
           superview.frame.height {
               tmp.origin.y = superview.frame.height - tmp.height
           }
    
           super.frame = tmp
           }
       }
    }
    }
    

    demo查看(https://github.com/timelywind/TabBarFit_iPhoneX_Demo)

    参考:https://stackoverflow.com/a/47225653/1553324

    谢谢!

    相关文章

      网友评论

      • 明明是个呆子:我提供一个更简单的方式,用KVO实现,监听tabBar的frame发现iPhone X的环境下会出现frame的高度改变的情况,所以给出代码如下:
        //监听tabBar的frame
        tabBar.addObserver(self, forKeyPath: "frame", options: [.old, .new], context: nil)
        //释放观察者
        deinit {
        tabBar.removeObserver(self, forKeyPath: "frame")
        }
        //处理高度变化
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let tabBar = object as? UITabBar, keyPath == "frame" {
        if let oldFrame = change?[.oldKey] as? CGRect, let newFrame = change?[.newKey] as? CGRect {
        if oldFrame.size != newFrame.size {
        if oldFrame.height > newFrame.height {
        tabBar.frame = oldFrame
        } else {
        tabBar.frame = newFrame
        }
        }
        }
        }
        }
        明明是个呆子:@eddy_liu 这个方法只解决高度抖动的问题,至于push动画过程中tabbar视图的层次问题可能需要专门处理,暂时还没去研究
        明明是个呆子:@eddy_liu 这个目前来看没法处理,微信都有延迟,更何况我这业余的了:joy:
        eddy_liu:试了下可行,就是tabar的隐藏会有一些延时,这个不造怎么处理。。。
      • lunaSun:楼主有没有发现在 返回主页面的一瞬间 safeAreaInsets.bottom = 117
      • 云深不知处a:这个问题总算是解决了,谢谢
        timelyRain:不客气
      • zhangPeng丶:您好,safeAreaInsetsDidChange 这个方法时iOS11才有的把?那低版本中会不会crash?
        zhangPeng丶:@timelyRain 这个问题发生的原因能说说么~
        zhangPeng丶:@timelyRain 好的,谢谢
        timelyRain:不会的,因为父类没有这个方法,所以子类,不会进这个方法的

      本文标题:iPhone X push操作后tabBar偏移问题

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