In my tabBar based app I have subclassed the UINavigationBar. Let's say I have three of them: BlueNavBar, BlackNavBar and RedNavBar. It looks something like this:
//BlueNavBar.m
- (void)drawRect:(CGRect)rect {
self.tintColor = [UIColor colorWithRed:65.0f/255.0f green:(156.0f/255.0f) blue:(215.0f/255.0f) alpha:1.0];
UIImage *image = [[UIImage imageNamed:#"blueNavBar.png"]retain];
[image drawInRect:rect];
[image release];
}
I've assigned the subclassed navigationbar for each tab with Interface Builder. That is working great, no problems there.
In some viewControllers however i want to change the navigationBar during "pushViewController". Let's say I want to change the current navigationbar (which is for e.g. BlueNavBar) to the RedNavBar. How can I do this programmatically, without Interface Builder?
It depends on how you've designed the view controller classes themselves. One way to design what you need would be to set the navigation bar type (i.e. colour) when you create the view controller, before you push it on the stack. Something like:
SomeViewController* someViewController = [[SomeViewController alloc] initWithNibName:#"SomeView" bundle:nil];
someViewController.navigationBarStyle = NBStyleRed; // NBStyleRed defined as an enum somewhere
[self.navigationController pushViewController:someViewController animated:YES];
[someViewController release];
The setter method for navigationBarStyle would then (re)create an appropriately-coloured navigation bar for the view controller.
Related
i have set the custom color to navigation bar of QLPreviewController
but the problem is that i want dark color of navigation bar in QLPreviewController
even i have set the navigation bar translucent property to No
But i Dont know Why it is not working
I want it like belowed image
but it shows like this image
QLPreviewController *previewer = [[QLPreviewController alloc] init];
// Set data source
[previewer setDataSource:self];
[previewer setDelegate:self];
// Which item to preview
[previewer setCurrentPreviewItemIndex:index];
[previewer.view addGestureRecognizer:singleTap];
previewer.navigationController.navigationBar.translucent = NO;
previewer.navigationController.navigationBar.barTintColor = [UIColor redColor];
self.navigationController.navigationBar.translucent=NO;
self.navigationController.navigationBar.barTintColor = [UIColor redColor];
[self.navigationController pushViewController:previewer animated:TRUE ];
even i have also tried like this but it is also not working
- (id <QLPreviewItem>)previewController: (QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
// Break the path into it's components (filename and extension)
// Use the filename (index 0) and the extension (index 1) to get path
//lblFileName.text=[strFileName stringByReplacingOccurrencesOfString:#"movefile" withString:#""];
// For navigation bar color and text attributes of navigation bar
for (id object in controller.childViewControllers)
{
if ([object isKindOfClass:[UINavigationController class]])
{
UINavigationController *navController = object;
navController.navigationBar.translucent=NO;
navController.navigationBar.barTintColor = [UIColor redColor];;
navController.toolbar.translucent=NO;
navController.toolbar.barTintColor=[UIColor redColor];;
[navController.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], NSForegroundColorAttributeName, nil]];
}
}
NSString *strFilename=[[NSBundle mainBundle]pathForResource:#"final" ofType:#"png"];
return [NSURL fileURLWithPath:strFilename];
}
Please suggest me where i am going wrong
Thanks In Advance
The main problem is that when you try to set the translucency of the navigation bar, you haven't pushed the preview controller on the navigation stack yet.
At this point, the preview controller is allocated and instantiated, but its view has not been loaded or added to the view hierarchy, and the value of previewer.navigationController is nil. The value of self.navigationController is not nil at this point, but the translucency property you set here will be overwritten as a side effect of pushing the preview controller. The easiest way to get the effect you want, is to swap the order of the statements, like this:
[self.navigationController pushViewController:previewer animated:YES];
self.navigationController.navigationBar.translucent = NO;
Do note that with the translucency of the navigation bar set to NO, the previewed content will start under the navigation bar, which is probably not what you want. The easiest way to work around that issue, is to set the translucency property after the view of the preview controller has appeared on screen. You can do this by subclassing QLPreviewController:
#interface PreviewController : QLPreviewController
#end
#implementation PreviewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.navigationBar.translucent = NO;
}
Note that things get more complicated when you present the preview controller modally (rather than pushing it on a navigation stack). In that case, there is no navigation controller available to access the navigation bar and you need to rely on the internal view hierarchy of the QLPreviewController. The following code works in iOS7, but might break in a later version:
[self presentViewController:previewController animated:YES completion:^{
UIView *view = [[[previewController.view.subviews lastObject] subviews] lastObject];
if ([view isKindOfClass:[UINavigationBar class]])
{
((UINavigationBar *)view).translucent = NO;
}
}];
No need for subclassing. try this:
QLPreviewController * ql = [[QLPreviewController alloc] init];
...
[self showViewController:ql sender:self];
ql.navigationController.navigationBar.translucent = NO;
ql.edgesForExtendedLayout = UIRectEdgeNone;
If you want to present it modally, just put the previewController into a navigationController:
UINavigationController * navi = [[UINavigationController alloc] initWithRootViewController:ql];
ql.navigationController.navigationBar.translucent = NO;
ql.edgesForExtendedLayout = UIRectEdgeNone;
[self presentViewController:navi animated:YES completion:nil];
Instead of using QLPreviewController,y don't you use webview to load the pdf.But if you load pdf in webview you need to customise the buttons thats it.Its also look very similar to QLPreviewController.
NSURL *targetURL = [NSURL fileURLWithPath:path_pdf]; //path_pdf is pdf's path
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[webview_pdf loadRequest:request];
Well,try it once.
If Still, anyone wants to customize the Navigation bar of QLPreviewController then they can try creating a UIViewController and customize it as per requirement and then create QLPreviewController object and add it as a child view controller.
This will allow you to get rid of share button and you customize navigation bar color etc. this is working for me.
To know, how to add child view controller you can refer to this
I have built my app using Storyboards. I have a UITabBarController and a NavigationController embedded it that.
I am trying to customise my app with tint colors and I have managed to set a custom color for the Tabbar. I was able to access the tabbar from the rootViewController, however I cannot get access to the navigation bar. Is there anyway that I can easily access this?
Sample of my AppDelegate code is below.
Thanks
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.tabBarController = (UITabBarController*)self.window.rootViewController;
UITabBar *tabBar = self.tabBarController.tabBar;
[tabBar setSelectedImageTintColor:[UIColor greenColor]];
tabBar.tintColor = [UIColor colorWithRed:0.4 green:0.522 blue:0.129 alpha:1];
//This bit doesnt work
UINavigationController *navCon = self.tabBarController.navigationController;
navCon.navigationBar.tintColor = [UIColor colorWithRed:0.384 green:0.259 blue:0.161 alpha:1];
return YES;
}
If you're using navigation controllers, would expect them to embed the view controllers that are managed by the tab bar controller.
Try NSLog(#"%#", [self.tabBarController viewControllers]); and see whether it lists navigation controllers or your custom controller. For example, I created two view controllers that are triggered by my tab bar, one with and one without navigation and the above line shows:
(
"<UINavigationController: 0x6a35f20>",
"<SecondViewController: 0x6a39500>" )
So, I could get mine as [[self.tabBarController viewControllers] objectAtIndex:0].
Assuming you did no work with IBOutlet's, I suggest you maybe use them along with the XIB file. For example, In the header file:
IBOutlet UINavigationBar *aNavBar;
And then in the .m, switch:
UINavigationController *navCon = self.tabBarController.navigationController;
navCon.navigationBar.tintColor = [UIColor colorWithRed:0.384 green:0.259 blue:0.161 alpha:1];
With:
[aNavBar setTintColor:[UIColor colorWithRed:0.384 green:0.259 blue:0.161 alpha:1]];
And there you go! I made this quick, so tell me if it works or not.
-Justin A.
I have a problem with the display of my popover. After initWithContentViewController: and presentPopoverFromBarButtonItem:permittedArrowDirections:animated: it cuts corners of the navigation bar. How should I fix it?? Thanks.
This is the code I'm using
NavContr *nav = [NavContr new];
nav.navigationBar.backgroundColor = [UIColor redColor];
UIPopoverController *tempPop = [[UIPopoverController alloc] initWithContentViewController:nav];
[tempPop presentPopoverFromBarButtonItem:mainButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
EDIT: I have resolved this problem:
+ (void)configure:(UINavigationController *)navController {
UINavigationBar *navigationBar = navController.navigationBar;
UIView *contentView = nil;
for (UIView *view in navController.view.subviews) {
if ([[NSString stringWithFormat:#"%#", [view class]] isEqualToString:#"UILayoutContainerView"])
contentView = view;
}
// setting frame to navigation bar and content view
[navigationBar setFrame:CGRectMake(navigationBar.frame.origin.x, 0, navigationBar.frame.size.width, navigationBar.frame.size.height)];
[contentView setFrame:CGRectMake(contentView.frame.origin.x, 0, contentView.frame.size.width, contentView.frame.size.height + navigationBar.frame.size.height)];
[navController.view bringSubviewToFront:contentView];
for (UIView *customView in contentView.subviews)
customView.frame = CGRectMake(customView.frame.origin.x, customView.frame.origin.y + navigationBar.frame.size.height, customView.frame.size.width, customView.frame.size.height);
[contentView addSubview:navigationBar];
[contentView bringSubviewToFront:navigationBar];
}
This is probably because you have no root view controller, or are otherwise fiddling with the navigation controller in ways it was not meant to be played with. This is how you ought to be setting up the popover:
MyCustomViewController *viewController = [[UIViewController alloc] initWithNibName:#"MyCustomViewController" bundle:nil]; //or storyboard or whatever
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController]; //you should have a root view controller before displaying the popover
tintColor = [UIColor redColor];
UIPopoverController *tempPop = [[UIPopoverController alloc] initWithContentViewController:nav];
[tempPop presentPopoverFromBarButtonItem:mainButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
There are a few very important things going on here:
Your navigation controller should have a root view controller before you display it.
This code is using a standard UINavigationController instance. According to the documentation, you should not subclass UINavigationController, nor should you try and reinvent the wheel. Apple has created a complex and comprehensive framework, UIKit, that you can use to build amazing apps. If you try and step outside the box, you'll be creating an awful lot of work for yourself without any appreciable benefit.
This is using the tintColor property of the UINavigationBar class. If the tint is insufficient for your UI, you can also set the background image manually (refer to the docs).
If you want to make a popover with a navigation controller, use the built-in UINavigationController class. Don't subclass it and don't reinvent it. To customize the appearance of the navigationBar, use the UI_APPEARANCE_SELECTOR methods in the UINavigationBar class.
I get the solution before add CALayer the UIPopOverController shows like
after adding below lines in table view class i get the following UIPopOverController
#import <QuartzCore/QuartzCore.h>
CALayer *imageLayer2 = self.tableView.layer;
[imageLayer2 setCornerRadius:-20];
[imageLayer2 setBorderWidth:1];
Try it in your project may be it works!!
Thanx
I have tried & replicate the issue you are facing, made some R&D. It's due to the line of code below :
nav.navigationBar.backgroundColor = [UIColor redColor];
While you set the background color of the navigation bar it will behave weird due the native shape of the pop up. Try and remove the below line, you will definitely have issue resolved.
If you are specifying the Rect where the popover appears, we've found that using decimals can result in weird distortions like that. Be sure you're using whole number for origin and size.
I have a UITabBarController that manages 5 View Controllers. I create their tab bar items in their "init" methods so that they will be displayed before the view is loaded. I'm just wondering what way I should do it, because there seems to be so many ways. For example, for my DatePickerViewController:
- (id)init {
if((self = [super init])) {
// ================ THIS ==========================
UIImage *clockIcon = [UIImage imageNamed:#"clockicon.png"];
UITabBarItem *localTabBarItem = [[UITabBarItem alloc]
initWithTitle:#"Date" image:clockIcon tag:0];
[self setTabBarItem:localTabBarItem];
[localTabBarItem release];
// ================ OR THIS ========================
[self setTitle:#"Date"];
UITabBarItem *localTabBarItem = [[UITabBarItem alloc] init];
[localTabBarItem setImage:[UIImage imageNamed:#"clockicon.png"]];
[self setTabBarItem:localTabBarItem];
[localTabBarItem release];
// ================ OR THIS ========================
UITabBarItem *localTabBarItem = [[UITabBarItem alloc] init];
[localTabBarItem setTitle:#"Date"];
[localTabBarItem setImage:[UIImage imageNamed:#"clockicon.png"]];
[self setTabBarItem:localTabBarItem];
[localTabBarItem release];
}
return self;
}
Which way should I do it? And why is there a title for both the tabBarItem and the View Controller? And I don't think I need the tag (which is set in the first method).
Thanks!!
Well in my opinion any of these ways are ok, it might be more readible when you declare the UIImage in one line and set it in a different line rather than doing it all inline, but at the end you get the same result.
The TabBarItems have a title which is the text that will show in the tab bar item iteself. View Controllers have a title for Navigation Controller purposes, the View Controllers title is displayed in the NavigationControllers NavBar when set. And you do need tags, tags is the way you tell the buttons apart when someone click on them (when u manage the TabBar on your own).
The reason there are several ways to set the title is for convienece. You may want to display one title in the navigation bar and one title in the tab bar.
This actually quite common since there is less space to display text in the tab bar.
Like many things in Cocoa, there is more than one way to do it. The only "correctness" you need to be concerned about is what works best for your situation.
How can I change the color of navigation bar from its default blue color?
Thanks.
The UINavigationBar class has a UIColor *tintColor property that you can change in code.
Alternately this property is also exposed in the InterfaceBuilder UI design tool.
Assuming you have added the navigation bar programmatically and not in Interface Builder, just put this in your viewDidLoad method.
self.navigationController.navigationBar.tintColor = [UIColor grayColor];
TintColor property doesn't affect default subview of navigation bar as bottom border and shadow. Sometimes it's useful to override layout of navigation bar at all.
Despite navigationBar is read-only property for UINavigationController you can avoid
this restriction by "setValue:forKey:". This method was approved on 5 applications successfully submitted to AppStore.
You can subclass UINavigationBar and change drawRect: method as you want.
For example,
#implementation CustomNavigationBar
- (void) drawRect:(CGRect)rect
{
[super drawRect:rect];
UIImage *backgroundImage = ImageFromColor(WANTED_COLOR);
[backgroundImage drawInRect:rect];
}
After you can subclass UINavigationController and change initWithRootViewController:
- (id) initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (self)
{
CustomNavigationBar *navBar = [CustomNavigationBar new];
[self setValue:navBar forKey:#"navigationBar"];
}
return self;
}
Also you can vary this approach by making Category for UINavigationController and implementing method swizzling for initWithRootViewController:
P.S. Yesterday my new app appeared at AppStore without any problem with this approach.