Content is placed in a UIPageViewController using the UINavigationController

UPDATE 2

I ran and tested my application in iOS Simulator using a 4-inch device. If I launch using a 3.5 inch device, the shortcut does not jump. In my .xib, under the "Simulated metrics" section, I set it as a 4-inch full-screen Retina mode. Any idea why I only see this problem on a 4 inch device?

UPDATE 1

In IB, if I select “Navigation Bar” in Simulated Metrics, my label still jumps. The only way I can get my label to display correctly on the initial screen is to not set the navigation controller as my root window controller.

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

In my window, the rootViewController is set to UINavigationController, which rootViewController has a built-in UIPageViewController.

When my application loads, the original view is represented by content that is slightly pushed down, about the same size as the navigation bar. When I view the pageViewController, the content jumps to where it was placed in the nib, and all the other view controllers loaded with the pageViewController are accurate.

uipageviewcontroller with navigationcontroller

In my app appDelegate:

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

In 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]; } 
+57
ios objective-c xcode uinavigationcontroller uipageviewcontroller
Aug 13 '13 at 6:52
source share
15 answers

So, I am adding another answer after further development, and finally, I think I understood what was going on. It seems that in iOS7, the UIPageViewController has its own UIScrollView. Because of this, you need to set automaticallyAdjustsScrollViewInsets to false. Here is my viewDidLoad now:

 - (void)viewDidLoad { [super viewDidLoad]; self.automaticallyAdjustsScrollViewInsets = false; DetailViewController *detail = [[DetailViewController alloc] init]; [self setViewControllers:@[detail] direction:UIPageViewControllerNavigationDirectionForward animated:false completion:nil]; } 

There is no need to embed anything in viewWillLayoutSubviews (as one of my previous answers suggested).

+79
Nov 14 '13 at 21:50
source share

This is definitely called automaticallyAdjustsScrollViewInsets , like other posters (including @ djibouti33). However, this property looks strange in two ways:

  • It must be installed on the UINavigationController . If you install it on a child controller controlled by the UINavigationController , it will have no effect. one
  • This only applies when the scroll view has a zero index in the controller submissions. 2

These two caveats should explain the intermittent problems that others in the stream are facing.

TL; DR: The workaround I went with was to add a dummy view to the UIPageViewController with a zero index to avoid the setting applied to scrollView in the page controller, for example:

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

It would be better to set the contentInset in the scroll view yourself, but unfortunately the UIPageViewController does not display the scroll view.

+21
Nov 17 '14 at 20:19
source share

Uncheck the Under Top Bars box for both: UIPageViewController and your custom PageContentViewController :

enter image description here

+12
Aug 03 '15 at 22:41
source share

My initial answer solved the problem for a while, but after a while the same problem came back to bite me.

Using the following viewController hierarchy:

 -- UINavigationController -- MyPageViewController -- MyDetailViewController 

Here is what I did to solve it:

In 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 child view controller initially if it contained a // scroll view. by the time we're in layoutSubviews, pageViewController seems to // have gotten it bearings and everything is laid out just fine. - (void)viewWillLayoutSubviews { [self setViewControllers:@[self.initialViewController] direction:UIPageViewControllerNavigationDirectionForward animated:false completion:nil]; } 
+4
Sep 27 '13 at 21:11
source share

I have the same problem. I solve it by putting setViewControllers for the first page in the UIPageViewController viewDidLoad instead of setting when I make an instance of the UIPageViewController. Also, I need to set autoAdjustsScrollViewInsets to NO.

+3
Mar 25 '15 at 19:17
source share

I had a similar problem, but none of the solutions worked here. My problem was that whenever I went to the next page, the content would scroll up, ending in the correct position, but start at 20 pixels too high (obviously something to do with the status bar). My VC container was not a navigation VC. Pulling my hair for a while, the solution that ultimately worked for me was to make sure that none of the limitations in my VC content were connected to the top layout. This may or may not be feasible in your case, but it was in mine, and that was the only thing that decided the jump in content. It is also very curious that this problem only appeared when the transition style was set to scroll. Just changing it to the curl page, the problem disappeared. But I need a scroll. Hope this helps someone else.

+3
Jul 24 '15 at 10:15
source share

Try removing these 2 options on your storyboard.

enter image description here

+2
Feb 08 '17 at 14:25
source share

Try selecting PageViewController in the storyboard and uncheck the "Under Bottom Bars" and "Under Opaque Bars" checkboxes in the attribute inspector.

+1
Jul 31 '15 at 6:34
source share

Initially, the hierarchy of the view manager looked like this:

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

I set it up so that MyContainerViewController can control the toolbar. I narrowed my problem down to MyContainerViewController and then it occurred to me that I didn't even need it if I subclass UIPageViewController. Now my hierarchy looks like this:

 -- UINavigationController -- MyPageViewController -- MyDetailViewController 

MyPageViewController controls it with the toolbar , and everything works as expected on both the 4-inch and 3.5-inch devices.

0
Aug 14 '13 at 16:09
source share

As stated in "Bo:": setting self.edgesForExtendedLayout = UIRectEdgeNone; in viewDidLoad MyPageViewController solved the problem. - Bo

0
Mar 02 '15 at 9:34
source share

This is my first post on stack overflow, but I've been looking for a solution to this problem for more than a week now.

Here is the solution that I came up with, hope it works for someone else with the same problem.

I'm not sure how you initialize your frame for your detail view controller, but I'm going to suggest that you can use: self.view.frame.size.height;

try using: self.view.frame.size.height - = self.navigationController.navigationBar.bounds.size.height;

Hope this helps

0
Apr 02 '15 at 1:58
source share

I see the same problem as described by @Danny on iOS 9. I tried to update all my restrictions so that they were not limited to fields , but the problem persists. In the end, I had to migrate a hack similar to this as follows:

  • For each content page displayed in the UIPageViewController, find the topmost restriction that is between the top of the view and the bottom of the top layout guide, and add the output for it in the view controller.
  • In each controller view with this output, add another property for the preferred top distance. These two outputs look like this (in Swift):

     @IBOutlet weak var topGuideConstraint: NSLayoutConstraint! var topDistance: CGFloat! 
  • In viewDidLoad() set topDistance value assigned to the constraint in the storyboard:

     override func viewDidLoad() { super.viewDidLoad() topDistance = topGuideConstraint.constant } 
  • In viewWillLayoutSubviews() verify that the constraint has the correct value by adjusting the height of the status bar when the value of topLayoutGuide.length is zero, which looks like this: during the transition , but not after it completes:

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

Repeat for each controller the content view displayed in the UIPageViewController. Adjust the offset if necessary if you also display the UINavigation panel.

This is an unsuccessful hack, and I hate doing it, but after many hours trying differently, I am at least glad that I have something that works so that I can move on.

0
Aug 08 '16 at 5:51 on
source share

As @ djibouti33 already wrote:

aBrowse pageView could not properly lay out its child view controller if it contains a scroll view. by the time we are in layoutSubviews, the pageViewController seems to have received it, and everything is laid out just fine.

Expecting layoutSubViews to load before setting any viewControllers to a UIPageViewController is the only thing that worked for me.

 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
Jan 05 '17 at 16:47
source share

None of them worked for me.

Here I found a solution

 var pageMenu : CAPSPageMenu? 

Instead of adding like this

 self.view.addSubview(pageMenu!.view) 

Add your CAPSPageMenu as shown below

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

Link: iOS Swift: SlidingMenuView incorrect position after imagePicker view

Happy coding!

0
Mar 09 '17 at 15:43
source share

A quick version of djibouti33's answer (excluding a line that is not part of resolving the problem)

Swift 3.0

 override func viewDidLoad() { super.viewDidLoad() self.automaticallyAdjustsScrollViewInsets = false } 
0
Jun 11 '17 at 8:07
source share



All Articles