I push a ViewController on my UINavigationController, but I see no 'back' button... the NavBar is empty but there.
In my storyboard, my initial View Controller is the NavigationController, and I set the 'Top Bar' to 'None' in the Simulated Metrics section. When I switch to Inferred or Navigation Bar, everything work ok, I see the back button with text "back". (but then all my View are ugly since I removed the NavBar for a reason).
How could I preserve my design (NavBar hidden/not there) and be able to push a new ViewController with a NavBar and Back button. NavBar on demand!
Thanks
Found a solution: just put my AppDelegate as the UINavigationController delegate and manually hide/show the NavBar.
In my Storyboard, the navigation controller is with:
Simulated Metrics -> Top Bar -> None
Navigation Controller -> Bar Visibility -> uncheck "Shows Navigation
Bar"
The AppDelegate .h/.m:
#interface AppDelegate : UIResponder <UIApplicationDelegate, UINavigationControllerDelegate>
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (something) {
navigationController.navigationBarHidden = TRUE;
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (somethingElse) {
navigationController.navigationBarHidden = FALSE;
}
}
You want to configure navigation in application
try this in ApplicationDidFinishLoading Method in App delegate
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[window makeKeyAndVisible];
[window addSubview:navController.view];
after use this to change view in action method of button
DetailViewController *ViewController = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushNavigationController:ViewController animated:YES];
Related
Okay, there's one thing I really don't understand.
I have a navigation controller (created in AppDelegate.m) as the first item in a tab bar controller (created in AppDelegate.h):
self.tabBarController.viewControllers = #[tabOneNavigationController, viewController2, viewController3, viewController4, viewController5];
In another class, I access this tabOneNavigationController by:
AppDelegate *apd = (AppDelegate *) [[UIApplication sharedApplication] delegate];
UINavigationController *navtab1 = [apd.tabBarController.viewControllers objectAtIndex:0];
And if I want to change the background of navtab1's navigation bar, I write:
[navtab1.navigationBar setBackgroundImage:navigationBackgroundImage forBarMetrics:UIBarMetricsDefault];
But for changing titleView, I've only seen examples using:
self.navigationItem.titleView = ...
but how do I do change navtab1's titleView?
Example: I have a custom TableViewCell, which contains a button, and when that button's clicked, it should change the titeView of navtab1 (in this case, self obviously doesn't have navigationItem property.
Here is use delegate methode of UINavigationController, This code might be helpful in your case:
#pragma mark -
#pragma mark - UINavigationController Delegate Methods
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UINavigationBar *morenavbar = navigationController.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
morenavitem.titleView = myCustomeView; // Add Here your custom UIView.
morenavitem.rightBarButtonItem.tintColor = [UIColor blackColor];
}
In above Method you also put image/color of NavigationBar.
current version of my project :
I have 5 different UIViewControllers in my app. I've set my
FirstViewController to be the Initial View Controller using the
Attributes Inspector. I move back and forth from one ViewController to
another by using buttons to which I assign modal segues, from one
ViewController to another, using the StoryBoard
What I want to change:
I want to keep the navigation buttons obviously, delete the modal segues and use
a UINavigationController instead. If I understand the concept
correctly, when using a UINavigationController I need to go into each
UIButton-IBAction and at the very end of the method I have to push the next
ViewController I want to move to, onto my NavigationController (do I also
have to pop the current one first?). However, I can't figure out how
to implement all that correctly.
What I've done so far:
I removed all modal segues from the storyboard and kept the navigation buttons along with their corresponding IBActions
I unchecked the box in the Attributes Inspector that was making my FirstViewController the initial View Controller of my app
I went into my AppDelegate.m and tried to create the Navigation Controller there and make my FirstViewController be the RootViewController
MyAppDelegate.m
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController *myFirstViewController = [[FirstViewController alloc] init];
UINavigationController *myNavigationController = [[UINavigationController alloc] initWithRootViewController:myFirstViewController];
[myNavigationController pushViewController:myFirstViewController animated:YES];
// Override point for customization after application launch.
return YES;
}
I then tried to test if the above was working by going into the IBAction of a
navigation button on my FirstViewController and implemented the
following in order to move to my SecondViewController when the
button is pressed :
FirstViewController.m
- (IBAction)goRightButton:(UIButton *)sender
{
// some code drawing the ButtonIsPressed UIImageView on the current View Controller
UIViewController *mySecondViewController = [[SecondViewController alloc] init];
[self.navigationController pushViewController:mySecondViewController animated:YES];
}
but nothing happens. What am I doing wrong ?
You are not linking your XIB file. Please add your navigation controller as
UIViewController *myFirstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:myFirstViewController];
Use following code to move from one view to another
UIViewController *mySecondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:mySecondViewController animated:YES];
If you are using a storyboard, you should just drag in the navigation controller there and hook it up to your app delegates. As long as it is the main storyboard, and you have identified a view controller to load first, you do not need to load any views in your app delegate.
In order to push a view programmatically that's in a storyboard, you need to do something like the following:
//bundle can be nil if in main bundle, which is default
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
MyCustomViewController *customVC = (MyCustomViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"customVC"];
//standard way
[self.navigationController pushViewController:customVC animated:YES];
//custom animation
[UIView transitionWithView:self.navigationController.view duration:0.5 options:UIViewAnimationOptionTransitionCurlUp animations:^{
[self.navigationController pushViewController:customVC animated:NO];
} completion:nil];
You identify the view controller with the identifier you add in the storyboard editor. Below are some screenshots to help show what I mean.
I have a tab bar item which is connected navigation controller with a UIViewController as the root view controller. The first touch on the tab bar item switches to that view. The second touch pops to the root view controller. The third touch does not scroll to the top.
I've seen this scroll-to-top behavior in other apps, but after searching the webs, I cannot find out anything about it.
Is this default behavior for scroll views or table views attached to tab bar items, or is it something I need to implement myself?
I realize this is an older question, but I'm also looking to create this behavior, and I think I have a simpler solution.
First, set your AppDelegate to be the delegate for your UITabBarController. Then add this method to AppDelegate.m:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if ([tabBarController.viewControllers objectAtIndex:tabBarController.selectedIndex]==viewController)
{
if ([viewController isKindOfClass:[UITableViewController class]])
{
[[(UITableViewController *)viewController tableView] setContentOffset:CGPointZero animated:YES];
}
else if ([viewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *nav = (UINavigationController *)viewController;
if ([nav.visibleViewController isKindOfClass:[UITableViewController class]])
[[(UITableViewController *)nav.visibleViewController tableView] setContentOffset:CGPointZero animated:YES];
}
}
return YES;
}
This works if your tab points at a UITableViewController or at a UINavigationController with a UITableViewController as the root view, and you don't have to worry about distinguishing between which UITableViewController is affected, sending notifications, etc.
Here is the solution to scroll to top of the table view when tab bar is clicked
In AppDelegate set tabbar delegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if (tabBarController.selectedIndex == 0) {
UINavigationController *selectedNav = [self.tabBarController.viewControllers objectAtIndex:self.tabBarController.selectedIndex];
UIViewController *currentVC = selectedNav.visibleViewController;
if([currentVC isMemberOfClass:NSClassFromString(#"HomeViewController")])
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshView" object:nil];
}
}
return YES;
}
In HomeViewController.m view did load listen for the notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshView:)
name:#"refreshView"
object:nil];
Refresh method
-(void)refreshView:(NSNotification *) notification{
if (self == self.navigationController.topViewController)
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}
No, this isn't default behaviour, you have to implement it yourself.
I'd do it by making the application delegate the delegate of the tab bar controller, and implement -tabBarController:didSelectViewController: to post a notification. Listen for that notification in your table view controller and do something like:
if (self == self.navigationController.topViewController)
[self.tableView scrollToTop];
Since your tab controller can only have one delegate, you may want to look at the answer to this question, which describes how to listen for the tap using KVO.
Is there a way to change the tint/background color of UIDocumentInteractionController navigationbar?
A cleaner version of #DOOManics implementation:
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return [self navigationController];
}
If you put the UIDocumentInteractionController onto a UINavigationController it will automatically take the color its navbar. This is probably your root view navcontroller.
You do this with the documentInteractionControllerViewControllerForPreview method:
- (UIViewController *) documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
{
// Use the rootViewController here so that the preview is pushed onto the navbar stack
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
return appDelegate.window.rootViewController;
}
[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:107.0/256.0 green:145.0/256.0 blue:35.0/256.0 alpha:1.0]];
Place this code in Appdelegate's didFinisLaunching method. It will change the color of the navigation bar for the whole app.
Try this code:
- (void)openEC:(NSURL*)url {
[UINavigationBar appearance].tintColor = [UIColor blueColor];
docController = [UIDocumentInteractionController interactionControllerWithURL:url];
[docController setDelegate:self];
[docController presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];
}
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller {
[UINavigationBar appearance].tintColor = [UIColor whiteColor];
}
Swift version to #dvdfrddsgn implementation
Try this : (You need to implement UIDocumentInteractionControllerDelegate)
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self.navigationController ?? self
}
If you're not using a navigationController, you can set the navigation bar color in the UIDocumentInteractionController by setting the correct settings on the View of the UIViewController where you launch the UIDocumentInteractionController from.
Let's say you have UIViewController viewController1 (from somewhere here you launch the UIDocumentInteractionController), with a View1 in the storyboard.
With the Storyboard open, click on the View1 from the list of elements on the viewController1 and go to "Attributes inspectors" on the right side. The Background and the Tint set there will be used in your UIDocumentInteractionController as well afterwards.
Then you can just use:
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
Note that inside the viewController1, you might have a Navigation Bar with different properties, and these will not be used in the UIDocumentInteractionController.
I have the following in the mainwindow.xib
Navigation Controller
List item
Tab bar controller
tabbar
firstViewController
SecondViewController
The entrypoint
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
navController.viewControllers = [NSArray arrayWithObject:tabBarController];
[window addSubview:navController.view];
[window makeKeyAndVisible];
return YES;
}
and now in the first viewcontroller i'm writing
-(void)loadView
{
if(rootAppDelegate==nil)
rootAppDelegate=(tabbarAppDelegate *) [[UIApplication sharedApplication]delegate];
listEmergencyItems= rootAppDelegate.listOfEmergencySectionItems;
self.rootAppDelegate.navController.navigationBarHidden = NO;
[super loadView];
}
and in the second viewcontroller i'm writing
- (void)loadView
{
if(rootAppDelegate==nil){
rootAppDelegate=(tabbarAppDelegate *) [[UIApplication sharedApplication]delegate];
}
listHospitalsItems= self.rootAppDelegate.listOfHospitalsItems;
self.rootAppDelegate.navController.navigationBarHidden = YES;
[super loadView];
}
And on the runtime, when it first loads the first view, i see the navigationbar where i need to navigate into a detail view.
And when i press the second tab bar item, i go to the second view, and the navigation bar gets hidden.
But when i press back on the first tabbar item, i.e. returning to the first viewcontroller. the navigation bar remains hidden.
Any idea?
The navigation bar won't show in the second view because neither view was placed on the navigationcontroller's stack. you want to use something like this in the parent to present a child view instead of overriding loadView
ViewToPresentViewController *myVController = [[ViewToPresentViewController alloc] initWithNibName:#"ViewToPresentViewController"
bundle:nil];
myVController.property = someValue;
[self.navigationController pushViewController:myVController
animated:YES];
[myVController release];
then, as i said previously, you can just use [self.navigationController setNavigationBarHidden:animated:]