web-dev-qa-db-ja.com

サブビューがビューエリアにない場合、iPhone Xでセーフエリアが正しく機能しない

ScrollViewに2つの子viewControllerが含まれています。 VC2が正しくレイアウトされていないことがわかります。

ビューがまだ画面上に表示されていない場合は見つかりました。 safeAreaInsetsは常に0です。

スクロールが終了したときにvc2.view.setNeedsLayout()を呼び出して、この問題を修正できます。しかし、レイアウトはスクロールが終了するまで正しくありません。

ドキュメント は言う

ビューが現在ビュー階層にインストールされていない場合、またはまだ画面に表示されていない場合、このプロパティのエッジインセットは0です。

どうすればこの状況を修正できますか?.

enter image description here

自動レイアウト enter image description hereenter image description here

14
PowHu

現在のビューのsafeAreaInsetsを参照する代わりに、UIApplicationに設定します。

(UIApplication.shared.delegate?.window??.safeAreaInsets.bottom)
10
ajayb

子ビューコントローラーで、ビューコントローラーadditionalSafeAreaInsetsをウィンドウのセーフエリアインセットと等しく設定すると、セーフエリアを考慮して正しくレイアウトされます。

viewDidLoad()viewWillTransition(to size: CGSize, with coordinator: UIVIewControllerTransitionCoordinatorの内部でこれを行う必要があることがわかりました

viewWillTransitionの内部では、コーディネーターのアニメーションブロックにadditionalSafeAreaInsetsを設定します。

coordinator.animate(alongsideTransition: { _ in
    if #available(iOS 11.0, *) {
        self.additionalSafeAreaInsets = UIApplication.shared.delegate?.window??.safeAreaInsets
    }
}, completion: nil)
3
Kylelol

私はカスタムページングビューコントローラーを作成していて、この問題と@PowHUに遭遇しました。

私にとってうまくいくように思えた唯一の解決策は、ストーリーボードのビューコントローラーのビュークラスを、作成したカスタムクラスAlwaysSafeAreaInsetsViewに設定することでした。

import UIKit

class AlwaysSafeAreaInsetsView: UIView {

    @available(iOS 11.0, *)
    override var safeAreaInsets: UIEdgeInsets {
        if let window = UIApplication.shared.keyWindow {
            return window.safeAreaInsets
        }
        return super.safeAreaInsets
    }

}
1
SamB

私が適切に表示する場合、コンテナービューはスーパービューの上部と下部に固定されています。これを安全領域に固定すると、子のビューコントローラが適切に配置されます。

0
jonaszmclaren