View Shifts on UIPageViewController - ios

I have a UIPageViewController with a first view that is inside a navigation controller. When the view is first displayed the nav bar covers the top part of the view. As soon as I start to swipe the page, the view drops below the nav bar. From then on the view will layout correctly. How can I fix this? What is causing this?

I was having the same problem. To fix it, set automaticallyAdjustsScrollViewInsets to NO before calling -setViewControllers:direction:animated:completion:.
self.automaticallyAdjustsScrollViewInsets = NO;
[self setViewControllers:#[firstPageViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];

Related

Show View on the top of navigation bar

I have a custom navigation and Home view in my app. On the click of button I want to show a View just like a left side view ( width is not equal to screen width) , on the top of navigation.
I have tried this:
LeftView.Layer.ZPosition = 1;
It is not working. If I set the Z index of navigation to -1, this hides complete navigation bar.
Try this :
[self.navigationController.view addSubview:yourSubView];
Try to add that view to UIWindow. This will add your view above navigation bar.
[[[[UIApplication sharedApplication] delegate] window] addSubview:yourView];
Add your custom navigation bar to the main view manually instead of using navigation controller's standard navigation bar. Then add your leftview as subview, in your main view. It will overlap navigation bar in this hierarchy.
This is a correct answer:
[self.navigationController.view addSubview:yourSubView];
Though it will not set the correct frame for the view, To set the correct frame for your view on the navigation bar, you have to set it in the viewDidAppear.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.navigationController.view addSubview:mTitleView];
}

Popping UIViewController causes previous UIViewControllers View to change position

I have a UINavigationController with a UIViewController set as it's rootController, it contains a background on its UIView using an image set just under the navBar. I then push onto the navigation controller a new UIViewController and when the back button is pushed, the previous controller looks different. Using the visual debugger I can see that the self.view has moved entirely down below the navBar where previously it was at the top. I have no idea and been racking my brains as to why this might be happening
-(void)pushIPhoneMessagingContactsController:(MessageContactsViewController *)contactsController{
self.selectorView.hidden = YES;
[self.navigationController pushViewController:contactsController animated:YES];
}
On the RootViewController (iPhoneMessagingNotificationsController)
-(void)viewWillAppear:(BOOL)animated{
self.selectorView.hidden = NO;
[[[self navigationItem] leftBarButtonItem] setTintColor:[UIColor blackColor]];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
if ([_displayType intValue] == MESSAGES_SHOWING) {
[self.notificationsViewController.view removeFromSuperview];
[self.contentView addSubview:_messagesViewController.view];
} else {
[self.messagesViewController.view removeFromSuperview];
[self.contentView addSubview:_notificationsViewController.view];
}
}
It seems the offending line was in the viewWillAppear method of the pushed UIViewController
self.navigationController.navigationBar.translucent = YES;
Somewhere else this navigationBar gets set as translucent:
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]
forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
and to make it solid colour again:
self.navigationController.navigationBar.shadowImage = nil;
self.navigationController.navigationBar.translucent = NO;
but this code seems to mess with the layout so perhaps there is another way to change the opacity of the navBar and statusBar without affecting the layout?
What you're currently trying to do is hide or show a selectorView which really only should appear for one specific view controller.
Here's an encapsulated way to solve this that makes your selectorView a part of the root view controller, removing the connection from other view controllers. They no longer have to know about it or hide it.
Add your selectorView to your rootViewController's navigation bar titleView. (You can do this in code, or drop it in Storyboard and add an IBOutlet for it.)
self.navigationItem.titleView = selectorView;
Now when you push another view controller, its title will replace your rootViewController's selectorView title (view). Your other view controllers don't need to know anything about that view.
This is a good design approach in general. Anytime you have a control that should only appear on one view controller's navigation bar, you want to make it a part of that view controller's navigationItem (titleView, or left/right bar button items.) iOS will display the control when it presents that view controller, and hide the control when that view controller is no longer the top view controller in the navigation controller stack.
As for the 64-pixel height issue, it's likely related to some complexity in the rootViewController hierarchy that shouldn't be there.
In iOS 7/8, a view's content, by default, appears under a translucent navigation bar. Apple freely managed this for you, by insetting the first view of the view hierarchy.
From your code, it appears that you're trying to "hide" or "show" the (un)selected viewController's view.
Each view controller should have a view it controls. A view controller shouldn't be trying to control other view controller's views, or adding other view controller's views to its own view hierarchy.
Here's Apple's recommended way to approach this. Use a containerView in your rootViewController. The whole purpose of a container view is to encapsulate a view controller within a view. As your selectorView changes which view to show, you have your container view transition from one view controller to the other. (If you're not familiar with how to do that, check out this answer.)
Pin the containerView to the rootViewController's view, so Auto Layout can size it for you.
Your view hierarchy now looks like view -> containerView, instead of view -> hidden view of unselected view controller, shown view of selected view controller. Apple can adjust the first view's inset, and nothing gets incorrectly offset (by the height of the navigation control).
Update:
This question talks about scrollViewInsets and how they can be set on a view-controller-by-view-controller basis. If you do have a view controller, and you don't want its content to appear under a bar, uncheck that box.
But the best way to handle this is to "standardize" your UI, so it isn't varying from view to view. Either make the bar always be translucent, or not always be translucent. This makes transitions less "jarring" for the users.

Page view controller inside Container presents View controller overtop UI

In my app, I have a nav bar and two toolbars visible in the main View Controller. I then have a container view in that main VC that fills the screen, behind the UI elements. I embedded a UIPageViewController in the container. I then set up a UICollectionViewController scene that is reused when swiping between the pages. This is done in code - see below. Basically, it presents the UICollectionViewController on screen.
It's working well, except when it appears on screen it covers up the UI of the main VC. I could change the height to reveal the UI, but I do want it to take up the entire screen. I just want it to lie behind the toolbars. That way when the user scrolls the Collection VC the content will be rendered underneath those translucent toolbars.
I understand why it's behaving the way it is, but I don't know how to fix it. I originally figured since it's all embedded in a Container it would respect the z-order of that container which appears fine in the storyboard, but I suppose if I'm just throwing the VC on screen in code I should expect such behavior. I'm just not sure how to get the desired behavior. Thanks for the assistance!
//the following code is in the main view controller
//set first page view controller
ContentCollectionViewController *startingViewController = [self viewControllerAtIndex:0]; //calls method below
[self.pageViewController setViewControllers:#[startingViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
//move page view controller down to reveal the underlying UI and show my issue
self.pageViewController.view.frame = CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height);
//display created page VC
[self addChildViewController:self.pageViewController];
[self.pageViewController didMoveToParentViewController:self];
[self.view addSubview:self.pageViewController.view];
//in the viewControllerAtIndex method:
ContentCollectionViewController *contentCollectionViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ContentCollectionViewController"];
//set properties here...
return contentCollectionViewController;
I was finally able to solve it by changing
[self.view addSubview:self.pageViewController.view];
to
[self.view insertSubview:self.pageViewController.view atIndex:1];

Navigation controller moves all views down by 64px in Storyboard despite it being hidden.

In the View Controller, I set the navigation bar so that
self.navigationController.navigationBar.hidden = YES;
However, I am running into the issue that whichever way my UIViews are laid out in Storyboard, all the UIViews at runtime are moved down 64px. Is there a way that I could set so that both the NavBar is hidden, and that it does not affect how the UIViews are laid out on screen?
Thanks!
Usually , I use this to hide navigationBar.
[self.navigationController setNavigationBarHidden:YES];
While,
self.navigationController.navigationBar.hidden = YES;
Is the property for UIView, this is a method for UINavigationController.

alternating between toolbar / tab bar

my app is structured as follow: UITabBarController > UINavigationController > ViewControllerOne > ViewControllerTwo.
the UINavigationBar has at the bottom the tab bar, now when the user navigates into the second view controller, i want to be able to hide the tab bar and replace is with a tool bar. i tried this code:
[self.navigationController.tabBarController.tabBar setHidden:YES];
[self.navigationController.toolbar setHidden:NO];
when i run the app the tab bar is hidden but the toolbar doesn't appear. plus, since the last VC is a table view controller, when i scroll through the cells there is a white gap between the table and the bottom of the view. how can i fix that?
That won't work because when you hide the tab bar like that the subviews won't be adjusted properly (that's why you get the white space). You'll have to use
self.hidesBottomBarWhenPushed = YES;
In your init method or awakeFromNib... and then
[self.navigationController setToolbarHidden:NO animated:YES];
In the viewDidLoad for example.
That way the tab bar controller's view is going to layout correctly it's subviews when you hide the tab bar. Just remember to call self.hidesBottomBarWhenPushed = NO; in your first view controller otherwise the tab bar is still going to be hidden when the second view controller is popped from the navigation stack.
Try to assigning toolbar with appropriate frame and adding it to self.tabBarController.view

Resources