私は最近、いくつかのコードを新しいiOS 11 Beta 5 SDKに移行しました。
私は今UITableViewから非常に紛らわしい振舞いを得ます。テーブルビュー自体はそれほど派手ではありません。私はカスタムセルを持っていますが、ほとんどの場合それはそれらの高さのためだけのものです。
テーブルビューでView Controllerをプッシュすると、セルが「上にスクロール」(またはテーブルビューフレーム全体が変更)され、プッシュ/ポップナビゲーションアニメーションに沿って下に移動する追加のアニメーションが表示されます。 gifを見てください。
私は手動でtableview
メソッドでloadView
を作成し、tableviewのスーパービューの先頭、末尾、上、下に等しくなるように自動レイアウト制約を設定します。スーパービューは、View Controllerのルートビューです。
View Controllerのプッシュコードは非常に標準的です。self.navigationController?.pushViewController(notifVC, animated: true)
同じコードは、iOS 10でも通常の動作を提供します。
何が悪いのかを教えてください。
編集:私は非常に単純なテーブルビューコントローラを作りました、そして私はそこで同じ振る舞いを再現することができます。コード:
class VerySimpleTableViewController : UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = String(indexPath.row)
cell.accessoryType = .disclosureIndicator
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let vc = VerySimpleTableViewController.init(style: .grouped)
self.navigationController?.pushViewController(vc, animated: true)
}
}
編集2:私はUINavigationBarの私のカスタマイズに問題を絞り込むことができました。私はこのようなカスタマイズをしています:
rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)
createFilledImage
は与えられたサイズと色で正方形の画像を作成します。
この行をコメントアウトすると、通常の動作に戻ります。
私はこの問題についての考えをいただければ幸いです。
これはUIScrollView's
(UITableViewはUIScrollviewのサブクラスです) new contentInsetAdjustmentBehavior
propertyに起因します。これは.automatic
に設定されていますデフォルトではです。
影響を受けるコントローラのviewDidLoadで、次のスニペットを使用してこの動作をオーバーライドできます。
tableView.contentInsetAdjustmentBehavior = .never
https://developer.Apple.com/documentation/uikit/uiscrollview/2902261- contentinsetadjustmentbehavior
Maggyの答えに加えて
OBJECTIVE-C
if (@available(iOS 11.0, *)) {
scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
この問題は、iOS 11.2のナビゲーション移行時にView Controllerのビューの
safeAreaInsets
が誤って設定されていたiOS 11のバグが原因で発生していました。contentInsetAdjustmentBehavior
を.never
に設定することは、他の望ましくない副作用を引き起こす可能性があるので、大きな回避策ではありません。回避策を使用する場合は、iOSバージョンが11.2以降の場合は必ず削除してください。- smileyborg氏(アップルのソフトウェアエンジニア)による言及
あなたは例えばdidFinishLaunchingWithOptionsの中でNSProxyを使用することによってアプリケーションを通してこの行動を一度に編集することができます:
if (@available(iOS 11.0, *)) {
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
これが私がどうやってこの問題を解決することができたか それでもiOS 11が自動的にインセットを設定することを可能にしている間 である。私はUITableViewController
を使っています。
tableView.insetsContentViewsToSafeArea = true
) - これは必要ではないかもしれませんが、それは私がしたことです。tableView.contentInsetAdjustmentBehavior = .scrollableAxes
)に設定します - .always
も機能する可能性がありますが、テストしませんでした。他のすべてが失敗した場合に試すべきもう一つのこと:
viewSafeAreaInsetsDidChange
UIViewController
メソッドをオーバーライドして、Table ViewがScroll Viewのインセットをセーフエリアのインセットに強制的に設定するようにします。これは、マギーの答えの「しない」設定と関連しています。
- (void)viewSafeAreaInsetsDidChange {
[super viewSafeAreaInsetsDidChange];
self.tableView.contentInset = self.view.safeAreaInsets;
}
注:UITableViewController
の場合、self.tableView
とself.view
は同じものにする必要があります。
これは意図した動作よりもバグのようです。ナビゲーションバーが半透明でない場合や背景画像が設定されている場合に発生します。
ContentInsetAdjustmentBehaviorを.neverに設定しただけでは、iPhone Xではコンテンツインセットが正しく設定されません。コンテンツはスクロールバーの下の下部に表示されます。
2つのことをする必要があります。
1。 push/pop時にscrollViewがアニメーション化しないようにする
2。それはiPhone Xのために必要とされるので、.automaticな振る舞いを保持します。ポートレートでは、コンテンツは下のスクロールバーの下に表示されます。
新しい簡単な解決策:XIBの:メインビューの一番上に新しいUIViewを追加します。他のサブビューなどに接続する必要はありません。
古い解決策:
注:UIScrollViewを横モードで使用している場合でも、水平インセットが正しく設定されないため(別のバグ?)、scrollViewの先頭/末尾をIBのsafeAreaInsetsに固定する必要があります。
注2:下記の解決策はまたtableViewが一番下までスクロールされ、そしてあなたがコントローラを押してポップバックすると、もう一番下にならないという問題があります。
override func viewDidLoad()
{
super.viewDidLoad()
// This parts gets rid of animation when pushing
if #available(iOS 11, *)
{
self.tableView.contentInsetAdjustmentBehavior = .never
}
}
override func viewDidDisappear(_ animated: Bool)
{
super.viewDidDisappear(animated)
// This parts gets rid of animation when popping
if #available(iOS 11, *)
{
self.tableView.contentInsetAdjustmentBehavior = .never
}
}
override func viewDidAppear(_ animated: Bool)
{
super.viewDidAppear(animated)
// This parts sets correct behaviour(insets are correct on iPhone X)
if #available(iOS 11, *)
{
self.tableView.contentInsetAdjustmentBehavior = .automatic
}
}
また、タブバーを使用している場合は、コレクションビューの下部のコンテンツインセットはゼロになります。このために、viewDidAppearの下にコードを置きます。
if #available(iOS 11, *) {
tableView.contentInset = self.collectionView.safeAreaInsets
}
上記のコードと合わせて、次のようにコードを追加してください。それは問題を解決しました
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // print(thisUISBTV.adjustedContentInset)
}
私はiOS 11.1のバグを再現することができますが、バグはiOS 11.2以降で修正されているようです。 http://openradar.appspot.com/34465226を参照してください。
私の場合、これはうまくいきました(viewDidLoadに入れて):
self.navigationController.navigationBar.translucent = YES;
このコードを削除する
self.edgesForExtendedLayout = UIRectEdgeNone
if #available(iOS 11, *) {
self.edgesForExtendedLayout = UIRectEdge.bottom
}
私はUISearchControllerをテーブルビューを持つカスタムresultsControllersと共に使用していました。新しいコントローラを結果コントローラにプッシュすると、tableviewが検索対象になりました。
上記のコードは完全に問題を解決しました
collectionView
またはtableView
の先頭にある余分なスペースを削除する
if #available(iOS 11.0, *) {
collectionView.contentInsetAdjustmentBehavior = .never
//tableView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
上記のコードcollectionView
またはtableView
はナビゲーションバーの下にあります。
以下のコードは、コレクションビューがナビゲーションの下に移動するのを防ぎます。
self.edgesForExtendedLayout = UIRectEdge.bottom
しかし、私はUICollectionViewのために以下のロジックとコードを使うのが好きです
四角形にエッジインセット値を適用して、その四角形で表される領域を拡大または縮小します。通常、エッジインセットは、ビューのフレームを変更するためにビューレイアウト中に使用されます。正の値を指定すると、フレームは指定された量だけインセット(または縮小)されます。負の値を指定すると、フレームは指定された量だけアウトセット(または拡大)されます。
collectionView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
//tableView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
UICollectionViewに最適な方法
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
}