アプリのデモを作成し、hidesBottomBarWhenPushedを使用して、プッシュアニメーションでTabbarを非表示にします。
しかし、Jump Button Tabbarをクリックすると、上に移動します!?このような:
VoidLessが提供する回答は、TabBarの問題を部分的にのみ修正します。 Tabbar内のレイアウトの問題は修正されますが、Tabbarを非表示にするViewControllerを使用すると、アニメーション中にTabbarが誤ってレンダリングされます(再現するには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
これが私の方法です。ActionTabBarなどのUITabBarのサブクラスを宣言します
スウィフト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
この問題は解決されています。なぜAppleがこの問題を解決しないのかはわからない。
IOS 12.1では、この問題はさらに深刻になります。ジェスチャを使用してポップバックすると、TabBarテキストがTabBar 毎回の上にジャンプするのがわかります。
注:この方法でこの問題を確実に解決できますが、それが良いアイデアかどうかはわかりません。また、構造が非常に複雑な場合は、多くのものを変更する必要があります。
このバグの別の解決策を提供します(seems Apple made)。
解決策は、タブバーが上に移動することを禁止することではありませんが、タブバーが上に移動したときに黒い領域が表示されないようにすることです
最も重要なことは、ビューコントローラーにサブビューを追加することです。このサブビューのフレームはウィンドウのサイズです。したがって、タブバーが上に移動すると、このサブビューは黒い領域の代わりに表示されます。
if (@available(iOS 11.0, *)) {
UIView* bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
bgView.autoresizingMask = UIViewAutoresizingNone;
bgView.backgroundColor = UIColorFromRGB(0xefeff4);
[self.view addSubview:bgView];
}
このメソッドの利便性は、タブバーをサブクラス化したり、navigationcontrollerのPushメソッドを上書きする必要がないことです。