【问题标题】:Content pushed down in a UIPageViewController with UINavigationController使用 UINavigationController 在 UIPageViewController 中下推内容
【发布时间】:2013-08-14 16:17:10
【问题描述】:

更新 2

我一直在使用 4 英寸设备在 iOS 模拟器中运行和测试我的应用程序。如果我使用 3.5 英寸设备运行,标签不会跳动。在我的 .xib 中,在 Simulated Metrics 下,我将其设置为 Retina 4 英寸全屏。知道为什么我只在 4 英寸设备上看到这个问题吗?

更新 1

在 IB 中,如果我在 Simulated Metrics 中选择“导航栏”,我的标签仍然会跳动。我可以让我的标签在第一个屏幕上正确呈现的唯一方法是不将导航控制器设置为我的窗口的根视图控制器。

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

我的窗口的 rootViewController 被设置为一个 UINavigationController,它的 rootViewController 嵌入了一个 UIPageViewController。

当我的应用加载时,初始视图的内容会被向下推一点,与导航栏的大小大致相同。当我滚动 pageViewController 时,内容会跳转到它放置在 nib 中的位置,并且 pageViewController 加载的所有其他 viewController 都很好。

在我的 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];
}

【问题讨论】:

  • 在“属性检查器”选项卡中设计界面(.xib 文件)时,从下拉菜单中选择顶部栏作为“导航栏”,然后相应地放置标签,标签将保持原样原来的地方。
  • 这实际上是我已经在做的。

标签: ios objective-c xcode uinavigationcontroller uipageviewcontroller


【解决方案1】:

Swift 版本的 djibouti33 的答案(不包括不属于问题解决的那一行)

Swift 3.0

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

【讨论】:

    【解决方案2】:

    以上都不适合我

    在这里我找到了解决方案

    var pageMenu : CAPSPageMenu?
    

    而不是像这样添加

    self.view.addSubview(pageMenu!.view)
    

    如下所示添加您的 CAPSPageMenu

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

    参考:iOS Swift : SlidingMenuView wrong Position after presenting imagePicker

    编码愉快!

    【讨论】:

      【解决方案3】:

      尝试在故事板上取消选中这两个选项

      【讨论】:

        【解决方案4】:

        正如@djibouti33 已经发布的那样:

        pageViewController 不能 如果它包含一个 滚动视图。当我们在 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)
        }
        

        【讨论】:

          【解决方案5】:

          我在 iOS 9 上看到了与 described by @Danny 相同的问题。我尝试将所有约束更新为 not constrained to the margins,但它并没有解决问题。我最终不得不采用类似于this one 的hack,如下所示;

          • 对于要在 UIPageViewController 中显示的每个内容页面,找到最顶部的约束,即视图顶部和顶部布局指南底部之间的约束,并将其添加到视图控制器的出口。
          • 在每个具有此类插座的视图控制器中,为首选顶部距离添加另一个属性。这两个出口看起来像这样(在 Swift 中):

            @IBOutlet weak var topGuideConstraint: NSLayoutConstraint!
            var topDistance: CGFloat!
            
          • viewDidLoad() 中,将topDistance 设置为故事板中分配给约束的值:

            override func viewDidLoad() {
                super.viewDidLoad()
                topDistance = topGuideConstraint.constant
            }
            
          • viewWillLayoutSubviews() 中,确保约束具有正确的值,当topLayoutGuide.length 为零时调整状态栏的高度,这似乎是during the transition 的情况,但一旦完成就不是:

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

          对 UIPageViewController 中显示的每个内容视图控制器重复。如果您还显示 UINavigation 栏,请适当调整偏移量。

          这是一个不幸的 hack,我讨厌不得不这样做,但在尝试不同的东西很多小时后,我至少很高兴有一些可行的东西,所以我可以继续前进。

          【讨论】:

            【解决方案6】:

            只需取消选中 Under Top Bars 即可:UIPageViewController 和您的自定义 PageContentViewController

            【讨论】:

            • 酱汁真棒!也必须对我的导航控制器执行此操作! :)
            【解决方案7】:

            尝试在 storyboard 中选择 PageViewController 并在 Attributes Inspector 中取消选中“Under Bottom Bars”和“Under Opaque Bars”。

            【讨论】:

              【解决方案8】:

              我遇到了类似的问题,但这里的解决方案都不起作用。我的问题是,每当我滚动到下一页时,内容都会向下跳,以正确的位置结束,但开始时 20 像素太高(显然与状态栏有关)。我的容器 VC 不是导航 VC。在拔掉我的头发一段时间后,最终对我有用的解决方案只是确保我的内容 VC 中的任何约束都没有连接到顶部布局指南。这在您的情况下可能可行,也可能不可行,但在我的情况下是可行的,这是解决内容跳转的唯一方法。也很奇怪,这个问题只有在过渡样式设置为滚动时才会出现。只需将其更改为 page curl 即可使问题消失。但我需要滚动。希望这对其他人有帮助。

              【讨论】:

              • 这里一样,只在过渡样式为滚动时发生
              • 我最终调整了这个技巧:knuspermagier.de/…,这样我就可以重新设置我的顶部布局指南约束(没有它会在不同尺寸的设备上导致问题)
              • 完美!这就是我所需要的!我对各自的布局指南的前导和尾随约束有同样的问题。我用这个来帮助。 iphonedev.tv/blog/2014/2/12/…
              【解决方案9】:

              这是我第一次在堆栈溢出上发帖,但我已经为这个问题寻找解决方案一个多星期了。

              这是我想出的一个解决方案,我希望它适用于其他有同样问题的人。

              我不确定您是如何为细节视图控制器初始化框架的,但我假设您可能会使用:self.view.frame.size.height;

              尝试使用: self.view.frame.size.height -= self.navigationController.navigationBar.bounds.size.height;

              希望对你有帮助

              【讨论】:

                【解决方案10】:

                我也有同样的问题。我通过将第一页的 setViewControllers 放在 UIPageViewController 的 viewDidLoad 中来解决它,而不是在创建 UIPageViewController 的实例时设置它。另外,我需要将automaticAdjustsScrollViewInsets 设置为NO。

                【讨论】:

                  【解决方案11】:

                  正如“Bo:”所说:把self.edgesForExtendedLayout = UIRectEdgeNone;在 MyPageViewController 的 viewDidLoad 中解决了这个问题。 - 博

                  【讨论】:

                    【解决方案12】:

                    这肯定是由automaticallyAdjustsScrollViewInsets 引起的,就像其他海报(包括@djibouti33)一样。但是,这个属性在两个方面很奇怪:

                    1. 必须在UINavigationController 上设置。如果将其设置在由UINavigationController 管理的子控制器上,则不会产生任何影响。 1
                    2. 仅当滚动视图在控制器子视图中的索引为零时才适用。 2

                    这两个警告应该解释线程中其他人遇到的间歇性问题。

                    TLDR:我采用的一种解决方法是在索引为零的UIPageViewController 添加一个虚拟视图,以避免将设置应用于页面控制器中的滚动视图,如下所示:

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

                    最好自己在滚动视图上设置contentInset,但不幸的是UIPageViewController 不会暴露滚动视图。

                    【讨论】:

                    • 这有点老套。
                    • 绝对是 hacky。但是这种神奇的行为取决于索引为零的滚动视图!
                    • 这个问题太疯狂了——绝对是最优雅的结果。
                    • 对我有帮助 =) 谢谢!
                    【解决方案13】:

                    所以我在进一步开发后添加了另一个答案,我终于想明白了发生了什么。好像在 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 中添加任何内容(正如我之前的答案之一所建议的那样)。

                    【讨论】:

                    • 请参阅下面的警告,automaticallyAdjustsScrollViewInsets 在应用于子视图控制器时不会做任何事情,例如 UINavigationViewControllerUITabBarController 内的视图控制器
                    • 成功了!一直在努力解决这个问题,谢谢!
                    【解决方案14】:

                    我原来的答案暂时解决了这个问题,但过了一会儿,同样的问题又来咬我了。

                    使用以下 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];
                    }
                    

                    【讨论】:

                    • 这是最终为我工作的那个 - self.automaticallyAdjustsScrollViewInsets = false;似乎什么也没做。
                    • @djibouti33:我想我知道发生了什么,见stackoverflow.com/a/26981213/99046
                    • 这对我有用——尤其是在层次结构中,将详细视图控制器嵌入到自己的导航控制器中
                    【解决方案15】:

                    最初我的视图控制器层次结构如下所示:

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

                    我这样设置它是为了让 MyContainerViewController 可以管理一个工具栏。我将问题缩小到 MyContainerViewController,然后我突然想到,如果我将 UIPageViewController 子类化,我什至不需要它。现在我的层次结构如下所示:

                    -- UINavigationController
                      -- MyPageViewController
                        -- MyDetailViewController
                    

                    MyPageViewController 管理它的 toolbar,并且在 4 英寸和 3.5 英寸设备上一切正常。

                    【讨论】:

                    • 对我来说,采用这种层次结构是不够的。把 self.edgesForExtendedLayout = UIRectEdgeNone;在 MyPageViewController 的 viewDidLoad 中解决了这个问题。
                    • 嘿,Bo,看看我的新答案,我选择它作为接受的答案。事实证明,采用这种新的层次结构并没有完全解决我的问题,因为这个问题在开发的后期又出现了。我还希望我的滚动视图在模糊的导航栏下方滚动,所以我无法使用您关于 edgeForExtendedLayout 的建议。不过,我的新答案似乎很可靠。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多