美文网首页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