MFMessageComposeViewController appearance iOS 7 - ios

I have an appearance proxy that sets the barTintColor property to green on UINavigationBar
[[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:54./255 green:165./255 blue:53./255 alpha:1]];
As needed I override this using appearanceWhenContainedIn:
[[UINavigationBar appearanceWhenContainedIn:[INFSearchViewController class], nil] setBarTintColor:[UIColor colorWithWhite:0.80 alpha:1]];
This works fine.
However when I present an MFMessageComposeViewController it adheres to the UINavigationBar proxy and looks like the following.
Which obviously looks terrible, I would prefer MFMessageComposeViewController to not adhere to the proxy but attempting to do
[[UINavigationBar appearanceWhenContainedIn:[MFMessageComposeViewController class], nil] setBarTintColor:[UIColor whiteColor]];
has no affect.
What course of action should I take here?

The hacky way: set the appearance back to the default white, present the modal, set the appearance to styled when the modal returns.
Or, reverse your thinking. Leave the global appearance as the default. Then you can selectively apply the styled nav bar where appropriate.
If "where appropriate" ends up being 90% of the app, just set up a thin subclass of UIViewController (or whatever view controller you use a lot) and that use that where you want the appearance.
[[UINavigationBar appearanceWhenContainedIn:[MyStyledViewController class], nil]
setBarTintColor:[UIColor colorWithRed:54./255 green:165./255 blue:53./255 alpha:1]];
And in each .h file, set your view controller superclass to MyStyledViewController rather than plain old UIViewController.

After digging around and trying a few different suggestions I arrived at a nice, non-hacky solution using a UINavigationController subclass.
This allows me to style all wanted nav bars once using the appearance proxy, with the exception of the MFMessageComposeViewController and MFMailComposeViewController which I'd prefer to look standard in order to communicate to the user that they are using core iOS functionality.
1 - Create a UINavigationController subclass.
2 - Style your nav bar using the appearance proxy as you were, but now using appearanceWhenContainedIn:
[[UINavigationBar appearanceWhenContainedIn:[KCStyledNavController class], nil] setBarTintColor:[UIColor redColor]];
[[UINavigationBar appearanceWhenContainedIn:[KCStyledNavController class], nil] setTintColor:[UIColor whiteColor]];
3 - Go into your storyboard, select all the the UINavigationControllers you want styled and change their custom class to your styled one.

Related

In Objective C, while presenting a ViewController how to change the color of NavigationBar?

I am able to change tho color of NavigationBar by giving BackgroundColor but than I am not able change the color of StatusBar. Please provide a solution.
You should change the barTintColor instead of the background color.
[self.navigationController setBarTintColor:[UIColor redNavigationBarColor]];
Chances are that you will probably need to change also the barButton color and/or the the title color and all that should probably apply to more than one screen. So, to save you some time, if you want to globally change all these, put the code below in your app delegate
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
[[UINavigationBar appearance] setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor whiteColor]}];
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
The code above will give you a red navigation bar with white title & buttons

Mail app segue (open-with) with incorrect navigation bar colors

I am currently attempting to open up the iOS mail all to create a draft with an attachment generated from my app. Here is a code snippet:
NSURL *fileLocation = [NSURL fileURLWithPath:self.site.dataFileLoc];
if(fileLocation) {
self.documentController = [UIDocumentInteractionController interactionControllerWithURL:fileLocation];
[self.documentController setDelegate:self];
[self.documentController presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];
}
However, what I am finding is that the navigation bar colours are completely off. In the AppDelegate, I am currently using these lines to set the global navigation bar appearance:
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"navbarBackground"] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearanceWhenContainedIn:[UIViewController class], nil] setShadowImage:[UIImage imageNamed:#"shadow"]];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor whiteColor]];
[[UITabBar appearance] setTintColor:[UIColor whiteColor]];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:NO];
Unfortunately, the title of the mail view controller that appears is still black, despite my attempt to set the bar style to black (which should make the title white in return) and blue bar buttons. It does, however, seem to work fine for the "presentPreviewAnimated" view controller. How can I make the navigation bar of the mail view controller consistent?
Are there any nibs associated??
I usually try to avoid the desired level of UI customization (navigation bar styles, colors, custom background w/image) because drawing UI at runtime (unless dynamically required) generally gets me in trouble...
Why not mock it up in a .nib file and make use of the fancy-dance-y tools in Xcode?? Can be therapeutic to quickly obtain the desired grain of detail without having to hit run...

UINavigationBar appearance setTintColour not working on ActivityItems

I'm trying to set the colour of the cancel buttonBarItem to white on the Message / Mail activityItems presented with the UIActivityViewController but whatever I do it doesn't change them.
The cancel remains the standard default blue used in iOS7 as do other items in these views that ideally I would like to change. I've tried using the code below in the AppDelegate which sets the colour correctly throughout the rest of the app but it doesn't work when these views are presented.
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
These settings do retain their values when added to AppDelegate and these views are presented as can be seen below.
[[UINavigationBar appearance] setBarTintColor:SOLIDTEALCOLOR];
[[UINavigationBar appearance] setTitleTextAttributes:#{ NSForegroundColorAttributeName: [UIColor whiteColor]}];
Do I need to roll my own ActivityViewController using bespoke SLComposeViewControllers for each activityItem to have this degree of control this colour? It seem like an unnecessary large amount of work for something that really shouldn't be an issue.

UIAppearance's "when not contained in"

I am currently spinning a complex web of UIAppearance modifiers*, and have come across a problem.
My usage of FlatUIKit's custom UIBarButton appearance protocol is causing MFMailComposerViewController to complain and stop working.
Therefore, instead of using UIAppearance's whenContainedIn method to specify classes that cause modification to occur, is there a way to exclude certain classes, i.e. a "when not contained in"?
*I am talking about the UIAppearance protocol that is used to predefine object appearance settings in the app's delegate.
You can use appearanceWhenContainedIn: to specify nil modification, which will give the default appearance:
[[UIBarButton appearance] setBarTintColor:[UIColor redColor]];
[[UIBarButton appearanceWhenContainedIn:[MFMailComposerViewController class], nil] setBarTintColor:nil];
As of iOS 9 SDK, there is also
[[UIBarButton appearance] setBarTintColor:[UIColor redColor]];
[[UIBarButton appearanceWhenContainedInInstancesOfClasses:#[[MFMailComposerViewController class]] setBarTintColor:nil];
Which can be used Swift-2 like so:
UIBarButton.appearance().barTintColor = UIColor.redColor()
UIBarButton.appearanceWhenContainedInInstancesOfClasses([MFMailComposerViewController.self]).barTintColor = nil
For me I used this one which works in iOS 10,
[[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar class]]] setTextColor:[UIColor darkGrayColor]];
My solution is to create a custom subclass of all the container view controllers that are being used in the app as the main UIWindow subviews (window's root view controller or presented view controllers), such as UINavigationController, UITabBarController or UISplitViewController.
Let's say the app is only using UINavigationController. Create a subclass:
class CustomizedNavigationController: UINavigationController {}
Then use the CustomizedNavigationController instead of plain UINavigationController everywhere in the app.
Also, instead of specifying the appearance for every UIBarButton, specify the appearance only when contained in the subclass:
UIBarButtonItem.appearance(whenContainedInInstancesOf:
[CustomizedNavigationController.self])
Because MFMailComposerViewController is not using the subclass, it won't get customized.

How to block UIAppearance proxy for some control

I set custom appearance to some of my UI classes.
[[UIBarButtonItem appearance] setTintColor:someColor];
...
[[UINavigationBar appearance] setBackgroundImage:someImage forBarMetrics:UIBarMetricsDefault];
So when i create UIBarButtonItem's or UINavigationBar's objects in my application they will have defined appearance.
But if want some object to have standart appearance(Not to use defined by proxy), I need to set all it's properties to default values manually.
So the quesion is: Is there any way to block using UIAppearance for some object?
Thank you.
Edit:
Its probably not 100% what you want to do but you could use appearanceWhenContainedIn.
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:[UIColor redColor]];
[[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil] setTintColor:[UIColor yellowColor]];
This way you can control the behavior to a certain degree.
Setting the properties to nil will use the default appearance:
[self.navigationController.navigationBar setTintColor:nil];

Resources