web-dev-qa-db-ja.com

UINavigationControllerを使用してUIPageViewControllerにプッシュダウンされたコンテンツ

更新2

4インチデバイスを使用して、iOSシミュレーターでアプリを実行およびテストしてきました。 3.5インチデバイスを使用して実行した場合、ラベルはジャンプしません。 .xibの[Simulated Metrics]で、Retina 4-inch Full Screenに設定しています。この問題が4インチデバイスでしか見られない理由はありますか?

更新1

IBでは、シミュレートされたメトリクスで「ナビゲーションバー」を選択すると、ラベルがジャンプします。最初の画面でラベルを正しくレンダリングできる唯一の方法は、ウィンドウのルートビューコントローラーとしてNavigation Controllerを設定しないことです。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

私のウィンドウのrootViewControllerは、rootViewControllerにUIPageViewControllerが埋め込まれているUINavigationControllerに設定されています。

アプリが読み込まれると、コンテンツが少し押し下げられた状態で、ナビゲーションバーとほぼ同じサイズの初期ビューが表示されます。 pageViewControllerをスクロールすると、コンテンツはnibに配置された場所にジャンプし、pageViewControllerによってロードされた他のすべてのviewControllerは問題ありません。

uipageviewcontroller with navigationcontroller

私のappDelegateで:

self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[ContainerViewController new]];

ContainerViewControllerで:

- (void)viewDidLoad {

    [super viewDidLoad];

    self.pvc = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
                                               navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                                                             options:nil];
    self.pvc.dataSource = self;
    self.pvc.delegate = self;
    DetailViewController *detail = [DetailViewController new];
    [self.pvc setViewControllers:@[detail]
                       direction:UIPageViewControllerNavigationDirectionForward
                        animated:false
                      completion:nil];

    [self addChildViewController:self.pvc];
    [self.view addSubview:self.pvc.view];
    [self.pvc didMoveToParentViewController:self];
}
60
djibouti33

それで、私はさらなる開発の後に別の答えを追加し、最終的に私は何が起こっているのかを理解したと思います。 iOS7では、UIPageViewControllerには独自のUIScrollViewがあるようです。このため、automaticallyAdjustsScrollViewInsetsをfalseに設定する必要があります。ここに私のviewDidLoadがあります:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = false;

    DetailViewController *detail = [[DetailViewController alloc] init];
    [self setViewControllers:@[detail]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:false
                  completion:nil];
}

viewWillLayoutSubviewsに何も入力する必要はありません(以前の回答の1つが示唆したように)。

83
djibouti33

これは、他のポスター(@ djibouti33を含む)のように、間違いなくautomaticallyAdjustsScrollViewInsetsが原因です。ただし、このプロパティは2つの点で奇妙です。

  1. UINavigationControllerに設定する必要があります。 UINavigationControllerで管理されている子コントローラーに設定した場合、効果はありません。 1
  2. スクロールビューがコントローラーのサブビューでインデックス0にある場合にのみ適用されます。 2

これら2つの警告は、スレッド内の他のユーザーが経験する断続的な問題を説明するものです。

TLDR:私が行った回避策は、インデックス0のUIPageViewControllerにダミービューを追加して、設定が適用されないようにすることです。次のように、ページコントローラー内のscrollView:

pageViewController.view.insertSubview(UIView(), atIndex: 0) // Swift

[pageViewController.view insertSubview: [UIView new] atIndex: 0]; // obj-c

スクロールビューにcontentInsetを設定する方が良いでしょうが、残念ながらUIPageViewControllerはスクロールビューを公開しません。

22
John Gibb

Under Top Barsの両方:UIPageViewControllerおよびカスタムPageContentViewController

enter image description here

私の元の答えは当面は問題を解決しましたが、しばらくすると同じ問題が戻ってきて噛みつきました。

次のviewController階層を使用します。

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

これを解決するために私がしたことは次のとおりです。

MyPageViewController.mで

@interface MyPageViewController () <delegates>
  @property (strong) MyDetailViewController *initialViewController;
@end

- (void)viewDidLoad
{
    ...

    // set this once, because we're going to use it in viewWillLayoutSubviews,
    // which gets called multiple times
    self.initialViewController = [MyDetailViewController new];
}

// the problem seemed to stem from the fact that a pageViewController couldn't
// properly lay out it's child view controller initially if it contained a 
// scroll view. by the time we're in layoutSubviews, pageViewController seems to
// have gotten it's bearings and everything is laid out just fine.
- (void)viewWillLayoutSubviews
{
    [self setViewControllers:@[self.initialViewController]
                   direction:UIPageViewControllerNavigationDirectionForward
                    animated:false
                  completion:nil];
}
4
djibouti33

ストーリーボードでこれらの2つのオプションをオフにしてみてください

enter image description here

3
apinho

私は同じ問題を抱えています。 UIPageViewControllerのインスタンスを作成するときに設定するのではなく、UIPageViewControllerのviewDidLoadの最初のページにsetViewControllersを配置することで解決します。また、私は自動的にAdjustsScrollViewInsetsをNOに設定する必要があります。

3
howa

私は同様の問題を抱えていましたが、ここで解決できるものはありません。私の問題は、次のページにスクロールするときはいつでも、コンテンツがジャンプして正しい位置で終わるが、20ピクセルの高さから始まることです(明らかにステータスバーと関係があります)。私のコンテナVCはnav VCではありませんでした。しばらく髪を引っ張った後、私のために機能するようになった解決策は、コンテンツの制約VCがトップレイアウトガイドに接続されていないことを確認することでした。これはあなたの場合には実行可能かもしれないし、そうでないかもしれませんが、私の場合はそうでした。そして、それがコンテンツのジャンプを解決した唯一のことでした。また、非常に奇妙なことに、この問題は遷移スタイルがスクロールするように設定されている場合にのみ現れました。これをページカールに変更するだけで、問題は解消されました。しかし、スクロールが必要でした。これが他の誰かに役立つことを願っています。

3
Danny

ストーリーボードでUIPageViewControllerを選択し、属性インスペクターで「下のバーの下」と「不透明なバーの下」のチェックを外してください。

1
acid beast

上記のどれも私にとってはうまくいきませんでした

ここで私は解決策を見つけました

var pageMenu : CAPSPageMenu?

このように追加する代わりに

self.view.addSubview(pageMenu!.view)

以下のようにCAPSPageMenuを追加します

addChildViewController(pageMenu!) 
self.view.addSubview(pageMenu!.view) 
pageMenu!.didMove(toParentViewController: self)

参照: iOS Swift:imagePicker提示後のSlidingMenuViewの間違った位置

ハッピーコーディング!

0
Sanju

「Bo:」で述べたように:self.edgesForExtendedLayout = UIRectEdgeNone; MyPageViewControllerのviewDidLoadで問題を解決しました。 –ボー

0
osxdirk

IOS 9で @ Dannyによって記述 と同じ問題が発生しています。すべての制約を更新して、 マージンに制約されない としたが、そうではなかった問題を修正します。次のように this one に似たハックを採用することになりました。

  • UIPageViewControllerに表示される各コンテンツページについて、最上部の制約、ビューの上部と上部レイアウトガイドの下部の間にある制約を見つけ、そのためのアウトレットをView Controllerに追加します。
  • そのようなアウトレットを持つ各View Controllerで、優先トップ距離に別のプロパティを追加します。 2つのアウトレットは次のようになります(Swift):

    _@IBOutlet weak var topGuideConstraint: NSLayoutConstraint!
    var topDistance: CGFloat!
    _
  • viewDidLoad()で、topDistanceをストーリーボードの制約に割り当てられた値に設定します。

    _override func viewDidLoad() {
        super.viewDidLoad()
        topDistance = topGuideConstraint.constant
    }
    _
  • viewWillLayoutSubviews()で、_topLayoutGuide.length_がゼロのときにステータスバーの高さを調整して、制約に適切な値が設定されていることを確認します 移行中 、ただし、一度は完了しません:

    _override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        topGuideConstraint.constant = topDistance + (
            topLayoutGuide.length == 0
                ? UIApplication.sharedApplication().statusBarFrame.size.height
                : 0
        )
    }
    _

UIPageViewControllerに表示されるすべてのコンテンツビューコントローラーに対して繰り返します。 UINavigationバーも表示している場合は、必要に応じてオフセットを調整します。

これは不幸なハックであり、やらなければならないのは嫌ですが、何時間もさまざまなことを試してみた後、先に進むことができるように機能するものがあればうれしいです。

0
theory

Djibouti33の回答のSwift版(問題解決の一部ではない行を除く)

Swift 3.

override func viewDidLoad() {
    super.viewDidLoad()
    self.automaticallyAdjustsScrollViewInsets = false
}
0
Kqtr

これはスタックオーバーフローに関する初めての投稿ですが、この問題の解決策を1週間以上探しています。

ここに私が思いついた解決策がありますが、これが同じ問題を抱えている他の誰にとってもうまくいくことを願っています。

ディテールビューコントローラーのフレームをどのように初期化するのかわかりませんが、次のように使用できると仮定します。self.view.frame.size.height;

使用してみてください:self.view.frame.size.height-= self.navigationController.navigationBar.bounds.size.height;

お役に立てれば

0
CalebDavis

@ djibouti33がすでに投稿したように:

pageViewControllerは、スクロールビューが含まれている場合、最初にその子View Controllerを適切にレイアウトできませんでした。 layoutSubviewsに到達する頃には、pageViewControllerはベアリングになっているようで、すべてがうまくレイアウトされています。

ViewControllersをUIPageViewControllerに設定する前に、layoutSubViewsがロードされるのを待つことで、私にとっては唯一うまくいきました。

override func viewDidLoad() {
    super.viewDidLoad()
    self.pageViewController = self.storyboard?.instantiateViewController(withIdentifier: "yourPageViewController") as? UIPageViewController       
    self.pageViewController?.dataSource = self

    pageViewController?.automaticallyAdjustsScrollViewInsets = false    
    self.pageViewController?.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.height)       
    self.addChildViewController(self.pageViewController!)        
    self.view.addSubview((self.pageViewController?.view)!)       
    self.pageViewController?.didMove(toParentViewController: self)
}


override func viewDidLayoutSubviews() {
    let startVC = self.viewControllerAtIndex(index: 0) as infoDataViewController     
    let viewControllers = NSArray(object: startVC)    
    self.pageViewController?.setViewControllers(viewControllers as? [UIViewController], direction: .forward, animated: true, completion: nil)
}
0
QitVision

最初、私のView Controllerの階層は次のようになりました。

-- UINavigationController
  -- MyContainerViewController
    -- UIPageViewController
      -- MyDetailViewController

MyContainerViewControllerがツールバーを管理できるように、このように設定しました。私の問題をMyContainerViewControllerに絞り込んだところ、UIPageViewControllerをサブクラス化する場合でもそれが必要ないこともありました。これで、私の階層は次のようになります。

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

MyPageViewControllertoolbarを管理し、4インチと3.5インチの両方のデバイスですべてが期待どおりに機能します。

0
djibouti33