UINavigationBar appearance proxy when contained in UIPopoverController - ios

I'm doing something that supposed to work in iOS7 and 8, but for some reason it doesn't. I want to customize navigation bar properties via appearance proxy and want it to be applied to all navigation bars even the ones that are inside UIPopover.
So, first step I do the following:
UINavigationBar *appearance = [UINavigationBar appearance];
appearance.barTintColor = [UIColor redColor];
appearance.titleTextAttributes = #{
NSForegroundColorAttributeName: [UIColor yellowColor]
};
This supposed to make all navigation bars red with yellow title. Works in iOS8. Mostly work in iOS7. For some reason when view controller is being presented inside UIPopoverController - it gets default appearance.
This is how I present popover (nothing fancy - almost standard sample code):
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"vc2"];
vc.title = #"View Controller 2";
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.popover = [[UIPopoverController alloc] initWithContentViewController:nav];
[self.popover presentPopoverFromRect:CGRectMake(100, 100, 100, 100) inView:self.view permittedArrowDirections:0 animated:YES];
Ok, so I decided to try appearanceWhenContainedIn and explicitly set its appearance there. Added the following code to initial appearance customization:
appearance = [UINavigationBar appearanceWhenContainedIn:[UIPopoverController class], nil];
appearance.barTintColor = [UIColor greenColor];
appearance.titleTextAttributes = #{
NSForegroundColorAttributeName: [UIColor blueColor]
};
Now. For some reason this last code doesn't affect anything. In iOS8 navigation bars inside UIPopoverControllers are still red + yellow, not green + blue, and iOS7 still uses default appearance.
What am I doing wrong here?
Here is link to the test project: https://dl.dropboxusercontent.com/u/6402890/TestAppearance.zip

For iOS 8
NS_CLASS_AVAILABLE_IOS(8_0) #interface UIPopoverPresentationController : UIPresentationController
Using the following worked for me. Navigation controller is contained in the UIPopoverPresentationController.
appearance = [UINavigationBar appearanceWhenContainedIn:[UIPopoverPresentationController class], nil];
For iOS 7
appearance = [UINavigationBar appearanceWhenContainedIn:[UIPopoverController class], nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
nav.navigationBar.barStyle = UIBarStyleBlack;
If navigation controller is loaded from storyboard, barStyle is also needed to be set to UIBarStyleBlack in storyboard.

Related

Objective-C: Back Button disappear after present/push ViewController from AppsDelegate

The pic below is my storyboard and I wish to present the Upcoming VC at AppDelegate. Below is my code at AppDelegate I manage to present the Upcoming VC when called.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc=[sb instantiateViewControllerWithIdentifier:#"Upcoming"];
UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:vc];
nv.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.window.rootViewController presentViewController:nv animated:YES completion:nil];
At the Upcoming VC, I manage to present the navigationBar with title and background colour but my back button < remain missing. My back button is auto generated.
-(void)viewWillAppear:(BOOL)animated{
self.navigationController.navigationBar.hidden = NO;
[self.navigationItem setHidesBackButton:FALSE];
//====Make the navigation Bar appear===
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = nil;
//=== Set the navigation Back < color
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[self.navigationController.navigationBar setBarTintColor : [ UIColor grayColor]];
//=== Set the navigation Bar text color
[self.navigationController.navigationBar
setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor whiteColor]}];
self.navigationController.navigationBar.translucent = NO;
}
Please help.
What do you expect then ?
back button will be only visible when you push your UpcomingVC from existing ViewController
remember that just taking navigation bar in storyboard will now show backbutton automatically.
You can create full view controller hierarchy
Like
UpcomingVC is pushed from HomeVC then you can set HomeVC as root view controller embedded in UINavigationController and to the next line you can push
UpcomingVC with animation false
you can tyr this
StoryBoard to StoryBoard
ViewControllerName * next = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewControllerName"];
[self.navigationController pushViewController:next animated:YES];
you must be nib registered.

UITabBarItem Image is in Blue and not changed

Um using my own TabBarController which is ElWafyatTabBarController basically it inherits from UITabBarController.
In ElWafyatTabBarController.m -> viewDidLoad
I've created some ViewControllers, Then I created UINavigationController's with rootViewController to the viewControllers I've made in the step before.
then I've created UITabBarItem and set it with image and title for each navigation controller which has rootViewController to the viewControllers that I've created in the first step, and set the tabBarItem for these navigationController to these tabBarItem.
The problem I found is even the title for the UITabBarItem is shown correctly, but the image is displayed at blue Color.
FYI: I've created two images named test.png and test#2x.png with dimensions 32x32 and 64x64
and I still have these issue,
So any one can help ?
this is my Code:
ElWafyatTabBarController -> viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
HomeViewController *homeViewController = [[HomeViewController alloc]
initWithNibName:#"HomeViewController" bundle:nil];
NaaiViewController *naaiViewController = [[NaaiViewController alloc]
initWithNibName:#"NaaiViewController" bundle:nil];
MushatraViewController *mushatraViewController = [[MushatraViewController alloc]
initWithNibName:#"MushatraViewController" bundle:nil];
TakremViewController *takremViewController = [[TakremViewController alloc]
initWithNibName:#"TakremViewController" bundle:nil]
UINavigationController *homeNavC = [[UINavigationController alloc]initWithRootViewController:homeViewController];
UINavigationController *naaiNavC = [[UINavigationController alloc]initWithRootViewController:naaiViewController];
UINavigationController *mushatraNavC = [[UINavigationController alloc]initWithRootViewController:mushatraViewController];
UINavigationController *takremNavC = [[UINavigationController alloc]initWithRootViewController:takremViewController];
// Setup Controllers for Tab Bar. (first level).
// [homeNavC.tabBarItem setTitle:#"الرئيسية"];
// [naaiNavC.tabBarItem setTitle:#"نعي"];
// [mushatraNavC.tabBarItem setTitle:#"مشاطرة"];
// [takremNavC.tabBarItem setTitle:#"تكريم"];
homeNavC.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:UITextAttributeTextColor];
naaiNavC.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:UITextAttributeTextColor];
mushatraNavC.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:UITextAttributeTextColor];
takremNavC.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObject:[UIColor whiteColor] forKey:UITextAttributeTextColor];
homeNavC.navigationBar.barStyle = UIBarStyleBlack;
naaiNavC.navigationBar.barStyle = UIBarStyleBlack;
mushatraNavC.navigationBar.barStyle = UIBarStyleBlack;
takremNavC.navigationBar.barStyle = UIBarStyleBlack;
UITabBarItem* tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Colors" image:[UIImage imageNamed:#"test.png"] tag:9];
homeNavC.tabBarItem = tabBarItem;
myViewControllers = [ NSArray arrayWithObjects:takremNavC, mushatraNavC, naaiNavC, homeNavC,nil];
[self setViewControllers:myViewControllers animated:YES];
[self.tabBarController setSelectedIndex:3];
[self setSelectedIndex:3];
}
and these the output:
If you want to see your image, you need to set the image's rendering mode to UIImageRenderingModeAlwaysOriginal, otherwise the image is displayed as a template image. You should read the documentation on tab bars, it has this statement:
Tab Bar Item Icons
Each item in a tab bar can have a custom selected image and unselected
image. You can specify these images when you initialize a tab bar item
using the initWithTitle:image:selectedImage: method. Note that a tab
bar item image will be automatically rendered as a template image
within a tab bar, unless you explicitly set its rendering mode to
UIImageRenderingModeAlwaysOriginal. For more information, see Template
Images.
Go to Assets.xcassets > Click on you image > Attribute Inspector > Render As > Original Image
Blue is the default tint color for UITabbar in iOS 7. You can change it to whatever color you like by setting:
myTabbar.tintColor = [UIColor greenColor]; //Put the color of your choice
if you have UITabBar:
UITabBar *tabBar = _tabBarController.tabBar;
UITabBarItem *tabBarItem1 = [tabBar.items objectAtIndex:0];
set the image of tabBarItem1 like this :
[tabBarItem1 setFinishedSelectedImage:[UIImage imageNamed:#"Selected_your_image"] withFinishedUnselectedImage:[UIImage imageNamed:#"UNSelected_your_image"]];
set selected and unselectedimage every UITabBarItem(s) of UITabBar.

Black Translucent Navigation Bar Flashes Opaque on First Push

I have a Navigation Controller where I set the navigationBar.barStyle = UIBarStyleBlack and the navigationBar.translucent = YES (as per Apple's advice since they deprecated UIBarStyleBlackTranslucent). In my two nib files (this is not using storyboard) in the simulated metrics I have Top Bar set to Black Navigation Bar.
SettingsViewController *controller = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
controller.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(closeSettings)];
controller.navigationController.navigationBar.barStyle = UIBarStyleBlack;
controller.navigationController.navigationBar.translucent = YES;
[self presentViewController:navController animated:YES completion:nil];
When I present the navigation controller, it opens up with the black translucent bar properly, but when I then push to the next table view, the navigation bar quickly fades to opaque and then back to translucent in the course of about 200ms. Its pretty much flashing opaque then back to translucent.
When I then push to the next table view, or go back (either by pressing the button in the top left of the nav bar, or by popping the view) it doesn't flash. It stays translucent the whole way through until the whole navigation controller is dismissed.
I thought this might be because of the way the nib was set up with an opaque bar, but I have tried every type of option (translucent, the regular blue, no bar) and it still does it.
Also, it does this across both completely separate navigation controllers in my app. Sorry if I am doing something obviously wrong, but I have tried so many combinations of options and am just at a loss.
Thanks!
I think you shouldn't use BarStyle at all but just :
[controller.navigationController.navigationBar setTintColor:[UIColor blackColor]];
[controller.navigationController.navigationBar setTranslucent:YES];
I would also try to animate the style change to get a smoother one with that in the presented view controller viewDidAppear method (think to begin with a black opaque bar in your code):
...
// Keep that where you want
SettingsViewController *controller = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
controller.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(closeSettings)];
// remove the two lines
[self presentViewController:navController animated:YES completion:nil];
}
Then in the SettingViewController code put :
- (void) viewDidAppear:(BOOL)animated {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
[controller.navigationController.navigationBar setTintColor:[UIColor blackColor]];
[controller.navigationController.navigationBar setTranslucent:YES];
[UIView commitAnimations];
}
Set appropriate value to your UIViewController instance property edgesForExtendedLayout, and set backgroundColor to your navigationController, for example:
self.edgesForExtendedLayout = UIRectEdgeBottom;
self.navigationController.view.backgroundColor = [UIColor whiteColor];
Hope this can help you.
SWIFT 5 VERSION
self.edgesForExtendedLayout = UIRectEdge.bottom
self.view.backgroundColor = .white

Customising the titleView in a UIPopoverController

On an iPad application, I want to be able to have multiple buttons in the top bar of a popover. I'm launching it like this:
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
pop = [[UIPopoverController alloc] initWithContentViewController:nc];
[pop presentPopoverFromRect:CGRectInset([tableView rectForRowAtIndexPath:indexPath], 10, 10)
inView:tableView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
pop.delegate = self;
[nc release];
In the viewDidLoad I want to set the titleView to contain multiple UIBarButtonItems. This is ok on a normal UINavigationController but I need to be able to do this and keep the custom style of the navigation bar on the popover.
I have tried setting the rightBarButtonItem to have a toolbar that contains buttons, but they take the format of the toolbar, which itself will not take the format/style of the popover.
It's a bit hackish, but you can create a truly transparent UIToolbar by subclassing and overriding drawRect: with an empty method. This will still draw the UIBarButtonItems on the toolbar, but not the toolbar itself.
Then, as Nils describes, you can create a bar button item out of the custom toolbar instance and add it as the rightBarButtonItem.
Why you don't use a custom UIView with a UIToolbar or UINavigationBar instead of UIPopoverController?
The effect, is the same!
First you need to set a delegate to the UINavigationController and then implement the nabigationController:willShowViewController:animated: method. In this method you can adjust the left and right bar button items.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
viewController.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]
initWithTitle:#"Image Source"
style:UIBarButtonItemStylePlain
target:self
action:#selector(cancelPressed)] autorelease];
}
I had the same problem, and here is what I did :
UIBarButtonItem *uiBarRefresh = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(forcerefresh)];
UIBarButtonItem *uiBarCurl = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPageCurl target:self action:#selector(showlist)];
UIToolbar_transparent* tools = [[UIToolbar_transparent alloc] initWithFrame:CGRectMake(0, 0, 133, 44.01)];
tools.barStyle = UIBarStyleBlackTranslucent;
tools.translucent = YES;
tools.backgroundColor = [UIColor clearColor];
tools.tintColor = self.navigationController.navigationBar.tintColor;
[tools setItems:[NSArray arrayWithObjects:flexItem,uiBarRefresh,uiBarCurl,nil] animated:NO];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tools];
This way you avoid the dull grey background, the pesky white underline, and you can completely customize how you want them positioned, by using fixed or flex spacings.
Best of luck with your project :]

Change tint of navigationBar and toolBar in a Popovercontroller with Navigationcontroller as view

I have a UINavigationController as my UIPopoverController's main view. I want to change the color tint of the navigationBar and toolBar but can't seem to get it to work.
Can anyone point me in the correct direction?
Here is the code I have in place that is not working.
Where Color Scheme = [UIColor colorWithRed:0.228 green:0.307 blue:0.492 alpha:1.000]
Here is the result from the NSLOG statement:
Color Scheme = UIDeviceRGBColorSpace 0.228 0.307 0.492 1
self.navController = [[UINavigationController alloc]
initWithRootViewController:serversMenu];
NSLog(#"Color Scheme = %#", self.appDelegate.colorScheme);
self.navController.navigationBar.tintColor = self.appDelegate.colorScheme;
self.navController.toolbar.tintColor = self.appDelegate.colorScheme;
self.navController.navigationBar.translucent = YES;
UIPopoverController *poc = [[UIPopoverController alloc] initWithContentViewController:self.navController];
poc.delegate = serversMenu;
serversMenu.mainPopOver = poc;
[poc release];
Thanks,
Rob
This works just fine:
AboutViewController *avc = [[AboutViewController alloc] init];
UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:avc] retain];
avc.navigationController.navigationBar.tintColor = [UIColor greyColor]; /* or whatever color you choose */
toolbar.tintColor = [UIColor greyColor];
Depends on how you choose to create your UIPopoverController
This is a bug ... and here's your fix ... Create a subclass of UINavigationBar with this as it's only new method:
- (void)setTintColor:(UIColor *)tintColor
{
// Bug workaround.
[super setTintColor:[self tintColor]];
}
I'm going to venture out on a limb and say this is a bug in iOS 4.2.x's PopOver/SplitView update ... I say "bug" because I had it set up pretty much like you and under 4.1 it works as expected. Now, under 4.2.x, it initially looks good, but once you open the masterView in a popover and then rotate back to the dual split, the masterView's navbar is silver (ios default), and no amount of hammer beating will get the masterView's navbar tint reset to your color scheme ...
I'm not exactly how to best put this in the form of a bug report, given that I don't fully understand it myself. But it used to work and we're not doing anything crazy!

Resources