web-dev-qa-db-ja.com

iOS 11 iPhone XシミュレータTabBarのアイコンとタイトルが互いに重なって表示されている

UITabBarコンポーネントに関してiPhone Xシミュレータに問題がある人はいますか?

私のものはアイコンとタイトルを互いの上にレンダリングしているようです、私は何かが足りないかどうかわからない、私はそれをiPhone 8シミュレータでも走らせたストーリーボード。

iPhone X:

iPhone X UITabBar bug

iPhone 8

iPhone 8 UITabBar works

120
adrian chen

ViewDidLayoutSubviewsのUITabBarでinvalidateIntrinsicContentSizeを呼び出すだけで、問題を回避できました。

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self.tabBar invalidateIntrinsicContentSize];
}

注:タブバーの下部は、安全な領域ではなくメインビューの下部に収まる必要があります。また、タブバーには高さの制限がありません。

36
David Hooper

VoidLessが提供する回答はTabBarの問題を部分的にしか解決しません。タブバー内のレイアウトの問題は解決されますが、タブバーを非表示にするviewcontrollerを使用すると、アニメーション中にタブバーが正しくレンダリングされません(再現するには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
22

問題を解決するためのトリックがあります。

あなたのUITabBarをUIViewの中に入れるだけです。

これは本当に私のために働いています。

または、もっと詳しく知りたい場合は、 リンク をたどってください。

20
Avineet Gupta

safeAreaのUITabBarsizeThatFits(_)をオーバーライドする

extension UITabBar {
    static let height: CGFloat = 49.0

    override open func sizeThatFits(_ size: CGSize) -> CGSize {
        guard let window = UIApplication.shared.keyWindow else {
            return super.sizeThatFits(size)
        }
        var sizeThatFits = super.sizeThatFits(size)
        if #available(iOS 11.0, *) {
            sizeThatFits.height = UITabBar.height + window.safeAreaInsets.bottom
        } else {
            sizeThatFits.height = UITabBar.height
        }
        return sizeThatFits
    }
}
10
Cruz

これは私のカスタムviewWillAppearUITabBarControllerに追加しました。

tabBar.invalidateIntrinsicContentSize()
tabBar.superview?.setNeedsLayout()
tabBar.superview?.layoutSubviews()
9
aaannjjaa

タブバーを下に移動する1ポイント下に移動するとうまくいきました。

もちろん、そうすることによってギャップを得るでしょう。それは何らかの方法で埋めなければなりませんが、テキスト/アイコンは適切に配置されます。

7
deej

私は同じ問題を抱えていました。

enter image description here

UITabBarの下部の制約にゼロ以外の定数を安全領域に設定したとします。

enter image description here

それは期待通りに働き始めます...

enter image description here

それが私がした唯一の変更であり、なぜそれが機能するのか私にはわかりませんが、誰かが知っていたいのであれば。

7
moliveira

ああ!実は魔法です!

私はついにAppleを呪った何時間もの後にこれを考え出した。

UIKitは実際にこれを処理します、そしてシフトされたタブバー項目は不正確な設定(そしておそらく実際のUIKitバグ)が原因であるようです。サブクラス化やバックグラウンドビューは必要ありません。

UITabBarは、スーパービューの下部に制限されている場合は「正常に」動作します。下部の安全領域には制限されません

Interface builderでも動作します。

正しいセットアップ

Working in IB

  1. IPhone Xとして表示しているインターフェイスビルダーで、UITabBarを一番下のセーフエリアインセットにスナップする場所までドラッグします。あなたがそれを落とすとき、それは正しく見えるはずです(一番下の端までスペースをいっぱいに満たしてください)。
  2. その後、 "Add Missing Constraints"を実行すれば、IBは正しい制約を追加し、あなたのタブバーはすべてのiPhoneで魔法のように機能します。 (一番下の制約はiPhone Xの安全でない領域の高さと等しい定数値を持っているように見えますが、実際には定数は0です)

時々それはまだ働かない

Broken in IB

愚かなのは、たとえあなたがIBが上記のステップで追加する正確な制約を追加したとしても、あなたはIBのバグを実際に見ることができるということです!

  1. UITabBarをドラッグして、一番下のセーフエリアの差し込みにスナップしないでください
  2. 先頭、末尾、および下部の制約をすべてスーパービューに追加する(安全ではない領域)奇妙なことに、下部の制約に対して制約インスペクタで[1番目と2番目の項目を反転]を実行すると、この問題は解決します。 ¯_(ツ)_ /¯
5
RyanM

SafeAreaInsetsを適用するためにサブクラス化されたUITabBarを使用することで修正されました:

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
            }
        }
        return size
    }
}
5
VoidLess

完了ブロックでモーダルを閉じた後に[tabController.view setNeedsLayout];を呼び出すことによって私のために解決しました。

[vc dismissViewControllerAnimated:YES completion:^(){ 
     UITabBarController* tabController = [UIApplication sharedApplication].delegate.window.rootViewController;
     [tabController.view setNeedsLayout];
}];
4
yogevbd

私の場合は、次のようにUITabBarControllerでカスタムのUITabBarの高さを設定したということでした。

  override func viewWillLayoutSubviews() {            
        var tabFrame = tabBar.frame
        tabFrame.size.height = 60
        tabFrame.Origin.y = self.view.frame.size.height - 60
        tabBar.frame = tabFrame
    }

このコードを削除すると、TabBarがiPhone Xで正しく表示されるようになりました。

2
Gytis

UITabBarは、ホームボタン/線より上になるように高さが増加していますが、サブビューを元の場所に描画し、サブビューの上にUITabBarItemをオーバーレイしています。

回避策としては、iPhone Xを検出してからタブバーがホームラインの上の安全な領域に表示されるようにビューの高さを32ピクセル縮小します。

たとえば、TabBarをプログラム的に作成している場合は、次のように置き換えます。

self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = self.tabBarController;

これとともに:

#define IS_IPHONEX (([[UIScreen mainScreen] bounds].size.height-812)?NO:YES)
self.tabBarController = [[UITabBarController alloc] init];    
self.window.rootViewController = [[UIViewController alloc] init] ;
if(IS_IPHONEX)
    self.window.rootViewController.view.frame = CGRectMake(self.window.rootViewController.view.frame.Origin.x, self.window.rootViewController.view.frame.Origin.y, self.window.rootViewController.view.frame.size.width, self.window.rootViewController.view.frame.size.height + 32) ;
[self.window.rootViewController.view addSubview:self.tabBarController.view];
self.tabBarController.tabBar.barTintColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;
self.window.rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;

注:ビューサイズとタブバーのレイアウトはOSによって設定されるため、これはバグになる可能性があります。それはおそらくここのiPhone Xヒューマンインターフェイスガイドラインのアップルのスクリーンショットに従って表示されるはずです: https://developer.Apple.com/ios/human-interface-guidelines/overview/iphone-x/

2
A.Badger

タブバーを選択し、インスペクタエディタで次のように「領域の相対余白を保存」チェックボックスを設定します。

enter image description here

1
AnnGoro

私は、ストーリーボードのView Controllerに手動で追加されたUITabBarを使用してこれに遭遇しました。セーフエリアの下部に0の定数で整列すると問題が発生しますが、1に変更すると問題が解決します。 UITabBarを通常より1ピクセルアップさせることは私のアプリケーションには受け入れられます。

1
Alan MacGregor

カスタムTabBarControllerでUITabBarのフレームを設定しようとしたときにも同じ問題が発生していました。

self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);

私がちょうどそれを新しいサイズに調整したとき、問題は消えました

if(IS_IPHONE_X){
    self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kPhoneXTabBarHeight, self.view.frame.size.width, kPhoneXTabBarHeight);
}
else{
    self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);
}
1
Evgeny

私はこの問題について私の頭をかいた。 tabBarがどのように初期化され、ビュー階層に追加されるかに関連しているようです。 invalidateIntrinsicContentSizeの呼び出し、フレームの設定、そしてUITabBarサブクラス内でのbottomInsetsなどの解決策も試しました。しかし、それらは一時的に動作しているようで、他のシナリオを中断するか、あいまいなレイアウトの問題を引き起こすことでタブバーを後退させます。問題をデバッグしているときに、UITabBarとcenterYAnchorに高さの制約を割り当てようとしましたが、どちらも問題を解決できませんでした。私は、ビューデバッガで、問題の再現前後でtabBarの高さが正しいことに気付きました。そのため、問題はサブビューにあると考えました。以下のコードを使用して、他のシナリオを後退させることなくこの問題を正常に解決しました。

- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    if (DEVICE_IS_IPHONEX())
    {
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            for (UIView *view in self.tabBar.subviews)
            {
                if ([NSStringFromClass(view.class) containsString:@"UITabBarButton"])
                {
                    if (@available (iOS 11, *))
                    {
                        [view.bottomAnchor constraintEqualToAnchor:view.superview.safeAreaLayoutGuide.bottomAnchor].active = YES;
                    }
                }
            }
        } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            [self.tabBar layoutSubviews];
        }];
    }
}

仮定:私はiPhone Xのためだけにこれをしています、それはそれが現時点では他のどの装置の上でも再生するように思われないので。 Appleが将来のiOSリリースでUITabBarButtonクラスの名前を変更しないという仮定に基づいています。 UITabBarButtonでこれを行っているのは、AppleがUITabBarにさらに内部サブビューを追加する場合、それに合わせてコードを変更する必要がある可能性がある場合だけです。

これがうまくいくかどうかを教えてください、提案や改善の余地があります。

これと同等のSwiftを作成するのは簡単なはずです。

1
Rushabh

このチュートリアルから:

https://github.com/eggswift/ESTabBarController

タブバーの初期化後にappdelegateクラスでこの行を書いた

(self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator

タブバーの問題を解決しました。

それがあなたの問題を解決することを願っています

ありがとう

1
Siddh

私にとってはこれですべての問題が修正されました。

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let currentHeight = tabBar.frame.height
        tabBar.frame = CGRect(x: 0, y: view.frame.size.height - currentHeight, width: view.frame.size.width, height: currentHeight)
    }
0
Durdu

私にとっては、[self.tabBar setBackgroundImage:] workを削除してください。おそらくUIKitのバグです。

0
KelaKing

私が見つけた最も簡単な解決策は、タブバーの下部とsafeAreaLayoutGuide.bottomAnchorの下部の間に0.2ポイントのスペースを追加することです。

tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -0.2)
0
Delta Whiskey

IPhoneの場合、これを行うことができます、サブクラスUITabBarController。

class MyTabBarController: UITabBarController {

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if #available(iOS 11, *) {
        self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true
        self.tabBar.invalidateIntrinsicContentSize()
    }
  }
}

ストーリーボードに移動してセーフエリアレイアウトガイドを使用し、UITabbarControllerのクラスを変更する MyTabBarControllerに

P.Sこのソリューションは、ユニバーサルアプリケーションおよびiPadの場合にはテストされていません。

0
NaXir

Tab Barに高さの制限がある場合は、それを削除してみてください。

同じ問題に直面し、これを削除すると問題が解決しました。

0
rustylepord

私は同様の問題を抱えていました。最初は正しくレンダリングされていましたが、tabBarItemの1つにbadgeValueを設定した後にレイアウトが壊れました。私が既に作成したUITabBarサブクラスで、UITabBarControllerをサブクラス化せずに動作したのはこれでした。

-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    NSLayoutYAxisAnchor *tabBarBottomAnchor = self.tabBar.bottomAnchor;
    NSLayoutYAxisAnchor *tabBarSuperviewBottomAnchor = self.tabBar.superview.bottomAnchor;
    [tabBarBottomAnchor constraintEqualToAnchor:tabBarSuperviewBottomAnchor].active = YES;
    [self.view layoutIfNeeded];
}

TabBarスーパ​​ービューを使用して、制約/アンカーが同じビュー階層にあることを確認し、クラッシュを回避します。

私の理解によると、これはUIKitのバグのように思われるので、自動レイアウトエンジンが再びタブバーを正しくレイアウトできるように、タブバーの制約を書き直すか再設定する必要があります。

0
rgkobashi

ストーリーボードでUITabBarControllerを使用していましたが、最初は問題なく動作していましたが、新しいXcodeバージョンにアップグレードすると、tabBarの高さに関連する問題が発生し始めました。

私にとっての修正は、既存のUITabBarControllerをストーリーボードから削除し、それをインターフェイスビルダーオブジェクトライブラリからドラッグして再作成することでした。

0
enigma

ストーリーボードに新しいUITabBarControllerを作成し、すべてのView Controllerをこの新しいUITabBarConttollerにプッシュしました。だから、すべてのiPhone Xシミュレータでうまくいきます。

0

@ 3倍の大きさのスプラッシュスクリーンを変更しようとすると(3726×6624)

0
Sob7y