pushViewController:animated: doesn't fully animate current controller out of bounds - ios

I have a UINavigationController thats width is 255 and the rootViewController is a UITableViewController that is of the same width. The problem is that when I push a new view controller, the current rootViewController animates about 1/3 of the way off screen and then stays visible while the new controller comes in and then it disappears. If I set animated to NO it works fine, but I need to animate it. There isn't anything fancy going on in the code, it is a simple push/pop setup when switching controllers. I added a video below to show you what it looks like. I put borders on the navigation controller (blue) and table view (orange). The code that does the push/pop is:
if ([[self.menuNavigationController topViewController] isKindOfClass:[TeamMenuViewController class]])
{
[self.menuNavigationController pushViewController:self.teamsViewController animated:YES];
}
else
{
[self.menuNavigationController popToRootViewControllerAnimated:YES];
}

It looks like your viewController.view that is being pushed on has a transparent background. The default UINavigationController animation in iOS 7 and 8 has an overlap effect.

Related

UIPresentationController not calling containerViewWillLayoutSubviews until after display

I have a UIPresentationController displaying a side menu over the main view with a fixed width of 300. Then from the side menu the user can open a full screen modal view. When the modal view is dismissed the menu view fills the screen during the dismissal animation (this is wrong). At the end of the animation containerViewWillLayoutSubviews is called and the menu corrects it's width to 300.
I do implement frameOfPresentedViewInContainerView. I am also implementing shouldPresentInFullscreen returning NO on the menu view (though this seems to not affect anything I can really determine).
Why isn't containerViewWillLayoutSubviews called before the dismssal animation? How should I be maintaining the menu view's width when it is covered and revealed?
Thanks to riadhluke for directing me to UIPresentationController changes size when another view controller is displayed on top of it
My solution is in my menu's prepareForSegue
UIViewController *destination = [segue destinationViewController];
if (destination.modalPresentationStyle == UIModalPresentationFullScreen) {
destination.modalPresentationStyle = UIModalPresentationOverFullScreen;
}
Which forces fullscreen modal presentations to be Over full screen, which causes the menu not to be lost, and therefore not re laid out post dismissal animation.

Creating custom push segue

I'm writing a custom segue class (HySegue) which allows views to animate the transition. The code is working great, except when under a UINavigationController stack. Actually, the transitions run and animate well, but the top UINavigationBar is what is causing me problems.
When first animating, I add the destination view as a subview of the source view. As such:
UIView * sourceView = sourceViewController.view;
UIView * destinationView = viewControllerToPresent.view;
// Force the source view to layout
[sourceView addSubview:destinationView];
[sourceView layoutIfNeeded];
When the transition is over, I present the destination view controller:
UIViewController * parentViewController = viewControllerToDismiss.parentViewController;
UIView * destinationView = destinationViewController.view;
// Break the view hierarchy that was setup earlier
[destinationView removeFromSuperview];
// When presenting in a UINavigationController stack, push the destination view controller
if ([parentViewController isKindOfClass:[UINavigationController class]]) {
[(UINavigationController *)parentViewController pushViewController:destinationViewController
animated:NO];
}
else {
// Present the destination view controller
[viewControllerToDismiss presentViewController:destinationViewController
animated:NO
completion:nil];
[viewControllerToDismiss willMoveToParentViewController:nil];
[viewControllerToDismiss.view removeFromSuperview];
[viewControllerToDismiss removeFromParentViewController];
[viewControllerToDismiss didMoveToParentViewController:nil];
}
The problem is that during the animation the destination view does not know that it's being pushed in a navigation stack and so the top bar, although visible, is not taken into account in the view's bounds. That is, the navigation bar is visible because it's visible for the source view controller, but the destination view controller knows nothing about it. When the animation finishes the destination view controller is pushed onto the stack, so it now knows about the navigation bar, and all my content with Top Space to Top Layout Guides constraints jumps down on the frame.
The top bar also doesn't show in IB. This is when I use my custom segue:
And this is when I use show segue:
Notice that the bar shows on the later but not on the former.
What I was wondering is how IB knows that it's a push segue. Is it some flag? Is it because of the specific class it's using? How would I make my custom segue also a push segue?
Edit: I loved the segue's type in prepareForSegue:sender: and it seems its type is UIStoryboardPushSegue, which is not a public or documented class. How can I can I solve it then? I already tried setting the destination view's frame and bounds from the source view.

UINaviagtionBar subview doesn't fade out during UIViewController "Back" transition

I have a UINavigationBar based app. I've created a custom UIView with some titles and added it as a subview to the navigation bar:
[self.navigationController.navigationBar addSubview:_navbarView];
Everything works ok until I hit the back button in the navigation bar and the UIViewController transition occurs.
The problem is that my custom view doesn't fade away like the others elements in the UINavigationBar, it just stays the same and disappears when the transition is complete.
I want it to fade away during the transition like the native elements of the UINavigationBar, is there any way to achieve this?
If you add a subview to the navigation bar, then it will just stay there; the navigation controller doesn't know to do anything special with it. You say your custom view has "some titles" - have you tried doing this instead?
self.navigationItem.titleView = _navbarView;
Then the navigation controller knows that the view should be used in place of your controller's title, and it should animate in and out.
If that doesn't work, you'll need to look at becoming the navigation controller's delegate. Since iOS7, this can get quite complex.
If you need custom navigation bar it could be a good idea to create UINavigationController with custom UINavigationBar
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
in your navigation bar class you can implement
- (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated
{
if (animated) {
//your_problem_view animation here
}
[super popNavigationItemAnimated];
}

Presenting a view controller of custom size with navigation

I want to present a view controller of custom size say (500,500). I try to do that with the below code, it works fine with a semi transparent light gray background if I present the view controller alone but when i put the view controller in a navigation controller (which I want to do) there is a black background that comes up, I dont want this and I want the gray one.
I did the following code with the help of this question:
iOS -- how do you control the size of a modal view controller?
MyViewController *vc=[[MyViewController alloc]initWithNibName:#"MyViewController" bundle:nil];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:vc];
nav.modalPresentationStyle=UIModalPresentationPageSheet;
[self.window.rootViewController presentModalViewController:nav animated:YES];
CGRect r = CGRectMake(self.window.rootViewController.view.bounds.size.width/2 - 250,
self.window.rootViewController.view.bounds.size.height/2 - 250,
500, 500);
r = [self.window.rootViewController.view convertRect:r toView:vc.view.superview.superview];
vc.view.superview.superview.frame = r;
Any guess, what I am missing here?? Or is there a easy way to present a custom size VC with navigation??
With navigation:
Without navigation: (i am using a dark background, so it may appear like it is black but it is not)
Just putting transparent overlay on the view controller and present it, sothat it looks like as what you actually want...
Also refer the following link,
Show modal view controller with custom frame in iPad
How to present a modal view controller with custom size in center?
iPad custom size of modal view controller
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html

How can I add a transparent view?

I want to push a view controller onto the navigation stack but I don't want its view to initially appear - in other words I want the view that was visible when the view controller is push to still be visible.
I tried setting the view controller's view's alpha value to 0.0 which I thought would make it transparent. But instead what is happening is that when I push the view controller on the the stack the screen is white. If I set the alpha to 1.0 then the view controller's view appears as expected.
Why is it white and not transparent?
you will have to add the view to the viewcontrollers manually
Not pushing it
For example do the following
YourViewController *vc = [[YourViewController alloc] init];
[self.view addSubview:vc.view];
vc.view.alpha = 0.0;
//Animate Here
vc.view.alpha = 1.0;
//Commit Animate Here
Please not that you will have to do some additional coding to implement the release of the vc, since now you have retained vc.view you will not be able to release vc easily,
Another solution is instead of implementing the second view as a viewcontoller implement it as uiview, and the xib class will be view and not uiviewcontroller
Maybe make sure that the opaque property is set to NO?
Or perhaps the view you're pushing on was built in interface builder, and you have a background color of white with another view you put on top of it and you only changed the opacity of the subview?

Resources