我构建了一个应用 Demo,在 Push Animation 中使用 hidesBottomBarWhenPushed 隐藏 Tabbar。
但是,当我点击跳转按钮标签栏向上移动!?像这样:
VoidLess 提供的答案仅部分修复了 TabBar 问题。它修复了标签栏内的布局问题,但是如果您使用隐藏标签栏的视图控制器,则标签栏在动画期间渲染不正确(重现它最好 2 有 2 个转场 - 一个模式和一个推送。如果您交替转场,您可以看到标签栏被渲染不合适)。请参阅下面修复这两个问题的代码。干得好苹果。
class SafeAreaFixTabBar: 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
}
}
}
}
Objective-C 代码:
@implementation VSTabBarFix {
UIEdgeInsets oldSafeAreaInsets;
}
- (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
这是我的方式。声明一个UITabBar的子类,比如ActionTabBar
迅速 3,4
class ActionTabBar: UITabBar {
override var frame: CGRect {
get {
return super.frame
}
set {
var tmp = newValue
if let superview = self.superview, tmp.maxY != superview.frame.height {
tmp.origin.y = superview.frame.height - tmp.height
}
super.frame = tmp
}
}
}
Objective-C
@implementation ActionTabbar
- (void)setFrame:(CGRect)frame
{
if (self.superview && CGRectGetMaxY(self.superview.bounds) != CGRectGetMaxY(frame)) {
frame.origin.y = CGRectGetHeight(self.superview.bounds) - CGRectGetHeight(frame);
}
[super setFrame:frame];
}
@end
声明 NavigationController 的子类
@implementation XXNavigationController
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[super pushViewController:viewController animated:animated];
CGRect frame = self.tabBarController.tabBar.frame;
frame.origin.y = [UIScreen mainScreen].bounds.size.height - frame.size.height;
self.tabBarController.tabBar.frame = frame;
}
编辑:12.1.1发布后,此问题已得到修复。您可以保留原始结构。
如果你改变你的结构
UITabBarController -> UINavigationController -> UIViewController
至
UINavigationController -> UITabBarController -> UIViewController
你会发现这个问题已经解决了。我真的不知道为什么苹果不解决这个问题。
在 iOS 12.1 中,这个问题变得更加严重。如果您使用手势弹回,您可以看到 TabBar 文本每次跳到 TabBar 上方。
注意:这种方式肯定可以解决这个问题,但我不确定它是否是一个好主意。另外,如果你的结构很复杂,你需要改变很多东西。
我将为这个错误提供另一种解决方案(似乎是苹果制造的)。
解决方法不是禁止tabbar上移,而是让tabbar上移时不显示黑色区域
核心是将子视图添加到您的视图控制器,因为它是最深的子视图,并且该子视图的框架是窗口大小。所以当标签栏向上移动时,该子视图将显示而不是黑色区域
if (@available(iOS 11.0, *)) {
UIView* bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
bgView.autoresizingMask = UIViewAutoresizingNone;
bgView.backgroundColor = UIColorFromRGB(0xefeff4);
[self.view addSubview:bgView];
}
此方法的方便之处在于您不必继承 tabbar 或覆盖 navigationcontroller 的 push 方法
这个问题似乎在 iOS 11.2 中已修复
只需将专门针对 iPhone X 的启动图像添加到大小为 1125 x 2436 的资产目录(因为它使用 @3x)。
我希望这能解决你的问题。