web-dev-qa-db-ja.com

iOS 7のテーブルビューがコンテンツインセットの自動調整に失敗する

プロジェクトをiOS7に移行しています。半透明のナビゲーションバーに関連する奇妙な問題に直面しています。

ビューコントローラーがあり、サブビューとしてtableviewがあります(ControllerAと呼びましょう)。 controllerAで新しいuinavigationcontrollerを初期化し、presentviewcontrollerを使用してモーダルモードで表示します。表示されるView Controllerのテーブルビューは、ナビゲーションバーによってブロックされます。 automaticallyAdjustsScrollViewInsets[〜#〜] yes [〜#〜]に設定しましたが、結果は変わりませんでした。 edgesForExtendedLayoutIRectEdgeNoneに設定できることはわかっていましたが、ナビゲーションバーが半透明になりません。

Table view get blocked

その後、テスト用に新しいView Controllerを作成しようとしました。ほとんど同じ要素が含まれています。しかし、結果は大きく異なります。テーブルビューのコンテンツはブロックされません。

enter image description here

結論

  1. YESに設定された2つのView ControllerのautomaticallyAdjustsScrollViewInsets
  2. プロジェクトはストーリーボードを使用していません
  3. 1つ目はXcode 4.6で作成され、2つ目はXcode 5で新しく作成されます
  4. Xibとコードの2つのクラスを比較しましたが、それほど違いはありません
38

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

55

ビューをナビゲーションバーの下に配置したいが、スクロールビューのコンテンツの上部がデフォルトでナビゲーションバーの下に配置されるように配置したい場合は、ビューがレイアウトされたら上部のインセットを手動で追加できます。これは、基本的に、最上位ビューがスクロールビューの場合にビューレイアウトシステムが行うことです。

-(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
        };
    }
}
47

トニーの答えに基づいて、テーブルビューを一時的に後ろに送り、調整を行ってからバックグラウンドビューを後ろに戻すことで、この問題をプログラムで回避することができました。私の場合、このアプローチにちらつきはありません。

View Controllerで:


- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [self.view sendSubviewToBack:self.tableView];
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self.view sendSubviewToBack:self.backgroundView];
}

明らかにself.viewに他のサブビューがある場合は、それらも並べ替える必要があります。

3
awulf

おそらく既にこれに対する答えが多すぎるかもしれませんが、ビューのサイズ変更をサポートするためにクリストファーのソリューションを取り、少し変更する必要がありました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のサブクラスは、contentInsetscrollViewviewDidLoadを変更できるようになり、尊重されます。ただし、contentInsetscrollViewUIEdgeInsetsZeroの場合:topLayoutGuideおよびbottomLayoutGuideに展開されます。

2
Ell Neal

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
}
1
Avt

ええ-少し迷惑です。

メインビュー内に、自動レイアウトを使用しない単一のテーブルビューを持つペン先があります。タブバー、ナビゲーションバー、ステータスバーがあり、アプリは5.0に戻る必要があります。 「iOS7とiOS6.1で並べて表示」することがきちんと機能するインターフェイスビルダーでは、テーブルがきちんとフィットします(iOS6/7デルタが適切に設定されると)。

ただし、デバイスまたはシミュレーターで実行すると、テーブルの上部に大きなギャップがありました。これは、ペン先でゼロに設定されたコンテンツの挿入(iOS6/7の垂直デルタとほぼ一致)の結果でした。

私が得た唯一の解決策は、[_ tableView setContentInset:UIEdgeInsetsZero]に入れるviewWillAppearでした。

画面上にかなりの結果が表示される別のいハック.....

0
Peter