プロジェクトをiOS7に移行しています。半透明のナビゲーションバーに関連する奇妙な問題に直面しています。
ビューコントローラーがあり、サブビューとしてtableviewがあります(ControllerAと呼びましょう)。 controllerAで新しいuinavigationcontrollerを初期化し、presentviewcontrollerを使用してモーダルモードで表示します。表示されるView Controllerのテーブルビューは、ナビゲーションバーによってブロックされます。 automaticallyAdjustsScrollViewInsetsを[〜#〜] yes [〜#〜]に設定しましたが、結果は変わりませんでした。 edgesForExtendedLayoutをIRectEdgeNoneに設定できることはわかっていましたが、ナビゲーションバーが半透明になりません。
その後、テスト用に新しいView Controllerを作成しようとしました。ほとんど同じ要素が含まれています。しかし、結果は大きく異なります。テーブルビューのコンテンツはブロックされません。
結論
Apple開発者フォーラム。2つの異なるケースがあります。
最初に追加されたView ControllerはUITableViewControllerです。そして、Appleはautoパディング。
2つ目は、View ControllerはUITableViewControllerではありません。そしてビュー階層には、UITableViewが含まれています。この場合、UITableview(またはScrollView)がviewControllerのメインビューまたはメインビューの最初のサブビューであれば、機能します。そうしないと、View Controllerはパディングするスクロールビューを認識せず、問題が発生します。
私の場合、View Controllerは2番目のものです。また、メインビューの最初のサブビューとして背景画像ビューがあります。したがって、失敗します。
Apple開発者フォーラムのリンク(アクセスするには開発者アカウントが必要です): https://devforums.Apple.com/message/900138#900138
ビューをナビゲーションバーの下に配置したいが、スクロールビューのコンテンツの上部がデフォルトでナビゲーションバーの下に配置されるように配置したい場合は、ビューがレイアウトされたら上部のインセットを手動で追加できます。これは、基本的に、最上位ビューがスクロールビューの場合にビューレイアウトシステムが行うことです。
-(void)viewDidLayoutSubviews {
if ([self respondsToSelector:@selector(topLayoutGuide)]) {
UIEdgeInsets currentInsets = self.scrollView.contentInset;
self.scrollView.contentInset = (UIEdgeInsets){
.top = self.topLayoutGuide.length,
.bottom = currentInsets.bottom,
.left = currentInsets.left,
.right = currentInsets.right
};
}
}
トニーの答えに基づいて、テーブルビューを一時的に後ろに送り、調整を行ってからバックグラウンドビューを後ろに戻すことで、この問題をプログラムで回避することができました。私の場合、このアプローチにちらつきはありません。
View Controllerで:
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[self.view sendSubviewToBack:self.tableView];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.view sendSubviewToBack:self.backgroundView];
}
明らかにself.view
に他のサブビューがある場合は、それらも並べ替える必要があります。
おそらく既にこれに対する答えが多すぎるかもしれませんが、ビューのサイズ変更をサポートするためにクリストファーのソリューションを取り、少し変更する必要がありましたandUIViewController
のサブクラスでコンテンツの挿入を変更できる。
@interface MyViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset;
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setScrollViewInitialContentInset:UIEdgeInsetsZero];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) {
[self setScrollViewInitialContentInset:[self.scrollView contentInset]];
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset];
if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) {
if ([self respondsToSelector:@selector(topLayoutGuide)]) {
scrollViewInset.top = [self.topLayoutGuide length];
}
if ([self respondsToSelector:@selector(bottomLayoutGuide)]) {
scrollViewInset.bottom = [self.bottomLayoutGuide length];
}
[self.scrollView setContentInset:scrollViewInset];
}
}
@end
ポイントを説明するには:
MyViewController
のサブクラスは、contentInset
のscrollView
のviewDidLoad
を変更できるようになり、尊重されます。ただし、contentInset
のscrollView
がUIEdgeInsetsZero
の場合:topLayoutGuide
およびbottomLayoutGuide
に展開されます。
Swift 2の@Christopher Pickslayソリューション
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let topInset = topLayoutGuide.length
inTableView.contentInset.top = topInset
inTableView.contentOffset.y = -topInset
inTableView.scrollIndicatorInsets.top = topInset
}
ええ-少し迷惑です。
メインビュー内に、自動レイアウトを使用しない単一のテーブルビューを持つペン先があります。タブバー、ナビゲーションバー、ステータスバーがあり、アプリは5.0に戻る必要があります。 「iOS7とiOS6.1で並べて表示」することがきちんと機能するインターフェイスビルダーでは、テーブルがきちんとフィットします(iOS6/7デルタが適切に設定されると)。
ただし、デバイスまたはシミュレーターで実行すると、テーブルの上部に大きなギャップがありました。これは、ペン先でゼロに設定されたコンテンツの挿入(iOS6/7の垂直デルタとほぼ一致)の結果でした。
私が得た唯一の解決策は、[_ tableView setContentInset:UIEdgeInsetsZero]に入れるviewWillAppearでした。
画面上にかなりの結果が表示される別のいハック.....