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

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];
}

Related

How to overlap navigation bar by adding view in swift?

I want to make a custom side bar by adding a new view to the view controller, the side bar will be in the yellow color background. I want my side bar also to overlap the navigation bar/item (green background color) in my view controller. but the navigation bar/item seems can't be overlapped by my side bar view, it seems only overlap the main view.
I tried to find the answer in stackoverflow, I find this Overlap navigation bar on ios 6 with other view, but the answer is on the Objective-C, I can't read Objective-C :(
What should I do to overlap navigation bar/item ? here is the screenshot of my view controller
I embed the navigation controller like this
There are plenty of implementations of slide-over or drawer containers.
What you need to do to get above the navigation bar is CONTAIN the navigation controller inside another view controller.
The stack would look like this.
MasterViewController
UINavigationController
RootViewController
Menu
See this one here:
Swift version of MMDrawerController
You can do this by changing your UIViewController hierarchy. For this you'll need three view controllers. First will contain everything, let's call it MasterViewController; second—your main content with navigation bar; and third—drawer.
In MasterViewController instantiate child view controllers and add them to your view controller hierarchy in viewDidLoad().
final class MasterViewController: UIViewController {
override func viewDidLoad() {
let drawerViewController = DrawerViewController()
let mainViewController = MainContentViewController()
let navigationController = UINavigationController(rootViewController: mainViewController)
addChildViewController(drawerViewController)
addChildViewController(navigationController)
view.addSubview(navigationController.view)
view.addSubview(drawerViewController.view)
}
}
Now you have navigationController.view that you can place or animate anywhere within view.

Setting titleView of UINavigationItem makes titleView disappear

I've set the titleView of a UIViewController's navigationItem after init(). After pushing the VC to UINavigationController, titleView appears correctly at first time. But when I change (re-set) a titleView to an other view, it suddenly disappears.
But when I push another view controller and navigate back, it suddenly appears.
Do I have to perform any actions after re-setting the titleView?
If you are not using tab bar controller, then in viewDidLoad
setting the title as self.title is better.I have mentioned Tab bar Controller because if you have a view controller (in a NavigationController) in a UITabBarController, then if you set self.title it overrides the name of the tab as well as the top title.
I think you maybe code like this:
self.navigationItem.titleView = self.yourView;
If your yourView is a custom class , it maybe remove from superView when you switch your viewcontroller to next one;
So code like this maybe solve your problem:
[self.navigationItem.titleView addSubview:yourView];

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.

How to hide UINavigationBar and UITabBar animated?

I have a UIViewController with UINavigationBar and UITabBar. I want to hide them animated: UINavigationBar flip upward and UITabBar flip downward. During the animation, I need the UIViewController's view resizing automatically to fulfil the new frame.
How to do it?
My structure is: UIViewController is placed in a UINavigationController as rootViewController, and the UINavigationController is placed in a UITabBarController as a childViewController.
I have tried resize the AppDelegate.window.frame directly but it will make other views.frame incorrect.
Since iOS8 you can use:
self.navigationController.hidesBarsOnSwipe = YES;
INFO
There is a bunch of nice new methods since iOS8:
UINavigationController
hidesBarsOnTap: A Boolean value indicating whether the navigation controller allows hiding of its bars using a tap gesture.
hidesBarsOnSwipe: A Boolean value indicating whether the navigation bar hides its bars in response to a swipe gesture.
hidesBarsWhenVerticallyCompact: A Boolean value indicating whether the navigation controller hides its bars in a vertically compact environment.
hidesBarsWhenKeyboardAppears: A Boolean value indicating whether the navigation controller hides its bars when the keyboard appears.

UIView overlapping Navigation Bar

In a viewController I programmatically create a UIView that has the same height of the screen. The problem is that navigation bar is still visible and clickable, but I want it to go under the new view. How can I do that?
EDIT: this is a screenshot of what I have now
Not sure if this is what you actually want, since hiding it is a quite acceptable thing to do. However you can hide the rightButtonItem and disable the left one:
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.backBarButtonItem.enabled = NO;
And to get back your right bar button, if you need it again somewhere:
self.navigationItem.rightBarButtonItem = self.*whatever*ButtonItem;
See if that works. I'm away from my Mac at the moment, so can't check it myself.
Right now you have taken navigation controller as a root view
controller (Maybe),In this case navigation controller overlaps the
UIVewController's view that's why it comes on the view so you need to
hide the Navigation controller.
What about making it hidden?
self.navigationController.navigationBarHidden = YES;

Resources