web-dev-qa-db-ja.com

iPhone Xの横長のUICollectionView

IPhone Xを横向きで使用する場合、safeAreaInsetsをチェックして、左右に適切に大きな溝を作成する必要があります。 UITableViewには、新しいinsetsContentViewsToSafeAreaプロパティ(デフォルトはtrue)があり、セルのコンテンツを安全な領域に自動的に保持します。

UICollectionViewに似たようなものがないように見えることに驚いています。縦方向にスクロールするコレクションビューの場合、横向きの場合は左側と右側が安全な領域に挿入されます(逆に、縦向きの場合は水平方向にスクロールするコレクションビューが挿入されます)。

この動作を保証する最も簡単な方法は、Collection View Controllerに追加することです。

- (void)viewSafeAreaInsetsDidChange {
    [super viewSafeAreaInsetsDidChange];
    UIEdgeInsets contentInset = self.collectionView.contentInset;
    contentInset.left = self.view.safeAreaInsets.left;
    contentInset.right = self.view.safeAreaInsets.right;
    self.collectionView.contentInset = contentInset;
}

... contentInset.left/rightが通常ゼロであると仮定します。

(注:はい、UICollectionViewControllerの場合、self.view.safeAreaInsetsである必要があります;これが呼び出された時点では、safeAreaInsetsへの変更はself.collectionViewにまだ反映されていません)

何か不足していますか?この定型文は非常にシンプルですが、今では画面の端に触れるeveryコレクションビューに効果的に必要です。 Appleがデフォルトでこれを有効にするものを提供しなかったことは本当に奇妙に思えます。

36
Wes Campaigne

NathanはさまざまなレイアウトでのUICollectionViewの汎用性については正しいのですが、主にUICollectionViewFlowLayoutを使用している「デフォルト」のケースについて心配していました。

IOS 11はsectionInsetReferenceプロパティをUICollectionViewFlowLayoutに追加しました。 公式ドキュメント には現在説明がありませんが、ヘッダーでは次のように説明されています

セクションのインセットが基準として定義される参照境界。デフォルトは.fromContentInsetです。

注:コンテンツのインセットは、常に最低限尊重されます。たとえば、sectionInsetReferenceが.fromSafeAreaに等しいが、調整されたコンテンツインセットがセーフエリアとセクションインセットの組み合わせよりも大きい場合、セクションコンテンツは代わりにコンテンツインセットに揃えられます。

可能な値は次のとおりです。

@available(iOS 11.0, *)
public enum UICollectionViewFlowLayoutSectionInsetReference : Int {
    case fromContentInset
    case fromSafeArea
    case fromLayoutMargins
}

そして、それを.fromSafeAreaに設定すると、希望する結果が得られます。つまり、最初は縦向きの場合:

initial portrait layout

次に、横向きに回転すると、セルは完全に安全な領域内に収まるように挿入されます。

iPhone X landscape collection view layout

...しかし、現在バグがあり、ポートレートafterに戻って回転すると、ビューは横向きになり、左にあるかのように動作し続けます/ right safeAreaInsetsはランドスケープ値に設定されます。

portrait layout following rotation from landscape

この問題に関してレーダー( rdar:// 3449199 )を提出しました。

40
Wes Campaigne

同じ問題がある。これは私のために働いた:

override func viewDidLoad() {
    if #available(iOS 11.0, *) {
        collectionView?.contentInsetAdjustmentBehavior = .always
    }
}

ドキュメント.always列挙型の場合:

コンテンツ調整には、常にセーフエリアのインセットを含めます。

このソリューションは、電話機が回転している場合にも正しく機能します。

51
petrsyn

助けてくれてありがとう。 UICollectionViewControllerサブクラスの場合、viewDidLoad()に次を追加しました(Swift 3):

if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
    if #available(iOS 11.0, *) {
        flowLayout.sectionInsetReference = .fromSafeArea
    }
}
8
anorskdev

上記の解決策は、コレクションセルビュー(およびセルの前縁または後縁に制約されているサブビュー)がコレクションビューの境界の全幅で、従うように設定されていないセーフエリアレイアウトガイド

注:@petrsynによる回答は、ほとんどの人が望んでいない可能性があるヘッダーを両側から挿入し、@ Wes Campaigneによる回答は、サブビューが先頭または末尾に添付されている全幅セルに対して実際には正しく機能しませんセルの端。

XibおよびStoryboardファイルをに設定し、セーフエリアレイアウトガイドを使用して、次に自動レイアウトを使用して制約を設定することは、特に古いプロジェクトから来ている人にとっては必須です安全領域にそれぞれ、またはコードで同様の操作を行います。

1
iAmcR

UICollectionViewは、さまざまなレイアウトに柔軟に対応することを目的としています。最も一般的なレイアウトは複数の行と列を持つグリッドですが、UICollectionViewを使用して非グリッドレイアウトを作成することもできます。

一方、UITableViewは全角セル用に設計されています。

したがって、UITableViewにはセーフエリアインセットを処理するためのビルトインサポートがあります。これは、テーブルビューのレイアウトが常に影響を受けるためです。 UICollectionViewはカスタムレイアウトを使用するため、万能ソリューションを提供するのではなく、実装ごとにこれらの問題を解決するのが理にかなっています。

0
nathangitter