60

更新 2

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

更新 1

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

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

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

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

带有导航控制器的 uipageviewcontroller

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

15 回答 15

83

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

于 2013-11-14T21:50:28.160 回答
22

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

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

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

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

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

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

最好自己设置contentInset滚动视图,但不幸的UIPageViewController是不会公开滚动视图。

于 2014-11-17T20:19:16.810 回答
12

只需取消选中Under Top BarsUIPageViewController和您的自定义PageContentViewController

在此处输入图像描述

于 2015-08-03T22:41:25.070 回答
4

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

使用以下 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];
}
于 2013-09-27T21:11:27.103 回答
4

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

于 2015-07-24T22:15:27.327 回答
3

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

于 2015-03-25T19:17:43.090 回答
3

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

在此处输入图像描述

于 2017-02-08T14:25:44.157 回答
1

尝试在情节提要中选择 PageViewController 并取消选中 Attributes Inspector 中的“Under Bottom Bars”和“Under Opaque Bars”。

于 2015-07-31T06:34:19.523 回答
0

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

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

我以这种方式设置它,以便 MyContainerViewController 可以管理工具栏。我将问题缩小到 MyContainerViewController,然后我想到如果我将 UIPageViewController 子类化,我什至不需要它。现在我的层次结构如下所示:

-- UINavigationController
  -- MyPageViewController
    -- MyDetailViewController

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

于 2013-08-14T16:09:55.347 回答
0

如“Bo:”所述:将 self.edgesForExtendedLayout = UIRectEdgeNone; 在 MyPageViewController 的 viewDidLoad 中解决了这个问题。– 博

于 2015-03-02T09:34:11.947 回答
0

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

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

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

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

希望这可以帮助

于 2015-04-02T01:58:46.487 回答
0

我看到了与@Danny在 iOS 9 上描述的相同的问题。我尝试将我的所有约束更新为它们不受 margins 约束,但它并没有解决问题。我最终不得不采用类似于以下的hack

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

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

    override func viewDidLoad() {
        super.viewDidLoad()
        topDistance = topGuideConstraint.constant
    }
    
  • viewWillLayoutSubviews()中,确保约束具有适当的值,当topLayoutGuide.length为 0 时调整状态栏的高度,这似乎是在 transition 期间的情况,但不是在完成后:

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

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

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

于 2016-08-08T17:51:42.787 回答
0

正如@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)
}
于 2017-01-05T16:47:46.453 回答
0

以上都不适合我

在这里我找到了解决方案

var pageMenu : CAPSPageMenu?

而不是像这样添加

self.view.addSubview(pageMenu!.view)

添加您的 CAPSPageMenu,如下所示

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

参考:iOS Swift:SlidingMenuView 出现 imagePicker 后的位置错误

快乐编码!

于 2017-03-09T15:43:18.590 回答
0

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

斯威夫特 3.0

override func viewDidLoad() {
    super.viewDidLoad()
    self.automaticallyAdjustsScrollViewInsets = false
}
于 2017-06-11T08:07:52.737 回答