Showing a white UINavigationBar for MFMailComposer with custom UINavigationBar themes in the app - ios

I have a simple app which is a UITableViewController. The app uses custom themes which applies a theme to the background and the UINavigationBar. From this view, I have a UINavigationBarItem (created in code) that brings up the email sheet with MFMailComposerViewController.
I'm finding some weird behaviour with the custom themed UINavigationBar and so I just want to remove the image and have a white UINavigationBar with black buttons (cancel, send, title).
I have the code below:
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"PDF"];
[mailer addAttachmentData:data mimeType:#"application/pdf" fileName:fileName];
NSString *emailBody = #"Please find attached PDF";
[mailer setMessageBody:emailBody isHTML:NO];
[self presentViewController:mailer animated:YES completion:^{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
mailer.navigationBar.titleTextAttributes = #{NSForegroundColorAttributeName : [UIColor blackColor]};
[[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]];
[[mailer navigationBar] setTintColor:[UIColor blackColor]];
}];
}
So I am actually removing the image there. The issue is that it works, but it doesn't actually make the buttons black as they should be. Also, in some instances, there are occurrences where the custom themed UINavigationBar image shows through. I want this to never happen.
I even went as far as creating a new class which was a subclass of MFMailComposer and setting the "theme" of the UINavigationBar to be a white created bar, but that still brought about the images sometimes.
What I want is to ensure the UINavigationBar never shows an image and always has black buttons for the Cancel, Title and Send.
Any thoughts would be really appreciated.
Update
With removing the setBarTintColor and setTintColor code above, I have noticed that the first time I invoke the MFMailComposeViewController, the theme is there in the UINavigationBar, but if I close that view, and re-open it, then the image is removed and the UINavigationBar is white. How can I get this to show up as white always, without a theme? I have also removed the code that removes the images to outside of the completion block, but that didn't make a difference.

To fill UINavigationBar with color you can use backgroundImage property with blank shadow image:
[[UINavigationBar appearance] setBackgroundImage:[self imageWithColor:[UIColor whiteColor]] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
-imageWithColor is an additional method for creating UIImage with selected color:
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Then set black text color and black status bar so it will be visible:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
[[UINavigationBar appearance] setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor blackColor]}];
And don't forget that these properties will be applied to every navigation bar.
Hope it helps! :)

Related

Buttons not visible on MFMailComposeViewController

I have a project working with custom navigationBar. I have added the following code before the initialising MFMailComposeViewController
// Create image for navigation background - portrait
UIImage *navBar = [[UIImage imageNamed:#"HeaderStrip.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UINavigationBar appearance] setBackgroundImage:navBar forBarMetrics:UIBarMetricsDefault];
// Create image for navigation background - landscape
UIImage *navBarL = [[UIImage imageNamed:#"HeaderStrip.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 100)];
[[UINavigationBar appearance] setBackgroundImage:navBarL forBarMetrics:UIBarMetricsLandscapePhone];
Here HeaderStrip.png is a simple red-colored image. Then in the following method, I've set the navigationBar back to original background image
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
Everything works as expected except the "Send" & "Cancel" buttons' visibility on the navigationBar of the mail composer. I've tried using tintColor before initialising MFMailComposeViewController:
[UINavigationBar appearance].tintColor = [UIColor whiteColor];
Got no difference.
I've also tried seting tintColor of the navigationBar of the composer after allocating, result same:
MFMailComposeViewController *mailer= [[MFMailComposeViewController alloc] init];
mailer.navigationBar.tintColor = [UIColor whiteColor];
Anyone got the solution of the issue? How to make the buttons visible?

iOS 7 tabBar-line, how to remove it?

Apple has added a tiny line over the tabBar in iOS 7 which is supposed to work as a shadow or fade between the tabBar and the UI
Since I am using a custom-made tabBar the line is quite irritating. How do you remove it? Please tell me it is possible, otherwise I need to redesign my whole app lol....
/ Regards
*Edit
Sloved my problem with the following line of code:
[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
UIImage* tabBarBackground = [UIImage imageNamed:#"tabbar_bg.png"];
[[UITabBar appearance] setShadowImage:tabBarBackground];
[[UITabBar appearance] setBackgroundImage:tabBarBackground];
These code works pretty well for me (I don't really have background image for tab bar):
[tab_main.tabBar setBackgroundImage:[[UIImage alloc] init]];
[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
And I use these code to add a frame too:
UIColor* color_green = UIColorFromRGB(0x348e5b);
tab_main.tabBar.layer.borderWidth = 0.50;
tab_main.tabBar.layer.borderColor = color_green.CGColor;
[[UITabBar appearance] setTintColor:color_green];
Hope that helps.
In iOS 8 the top border can be removed by setting the tab bar style to black in the inspector.
Swift
Nice simple solution:
Write this below code in your custom tab bar class. Then it will hide horizontal shadow line.
self.tabBar.setValue(true, forKey: "_hidesShadow")
Objective C
[self.tabBar setValue:#(YES) forKeyPath:#"_hidesShadow"];
self.tabBarController = [[UITabBarController alloc] init];
[[[self tabBarController] tabBar] setBackgroundImage:[UIImage imageNamed:#"YOURIMAGE.png"]];
[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
I'm not seeing anything in the UITabBar API for affecting that separator, but if the separator is within the UITabBar (a UIView subclass), I'd expect you can insert a new one-pixel-high UIView on top of it. You'd have to grab a slice of the image that you want to appear there and draw it in the new view. And I'm not sure if UITabBar would somehow prevent adding the subview or prevent the subview from being on top. But that's where I'd start.
Add the following code in AppDelegate.m didFinishLaunchingWithOptions: method
if ([[[UIDevice currentDevice] systemVersion] floatValue]>=7.0)
[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];
This worked for me
UIImage* tabBarBackground = [UIImage new];
if(!OSVersionIsAtLeastiOS7())
{
tabBarBackground = [UIImage imageNamed:#"whitebg"];
}
[[UITabBar appearance] setShadowImage:tabBarBackground];
[[UITabBar appearance] setBackgroundImage:tabBarBackground];
[_tabBarController.tabBar setBackgroundImage:[UIImage imageNamed:#"tabtarsprnt"]]; //your custom image
[self.tabBarController.tabBar setClipsToBounds:YES];
this code also solved the my issue
In my case I also needed to set a different shadow, in the end the only thing that worked while also setting a custom shadow was to add a single-point high UIView 1 point above the tab bar:
UIView *whiteLine = [[UIView alloc] initWithFrame:CGRectMake(0.0, -1.0, self.tabBar.frame.size.width, 1.0)];
whiteLine.backgroundColor = [UIColor whiteColor];
[self.tabBar addSubview:whiteLine];
Try this,
** Objective-C **
//Remove shadow image by assigning nil value.
[[UITabBar appearance] setShadowImage: nil];
// or
// Assing UIImage instance without image reference
[[UITabBar appearance] setShadowImage: [[UIImage alloc] init]];
** Swift **
//Remove shadow image by assigning nil value.
UITabBar.appearance().shadowImage = nil
// or
// Assing UIImage instance without image reference
UITabBar.appearance().shadowImage = UIImage()
Here is apple document for shadowImage.
#available(iOS 6.0, *)
open var shadowImage: UIImage?
Default is nil. When non-nil, a custom shadow image to show instead of
the default shadow image. For a custom shadow to be shown, a custom
background image must also be set with -setBackgroundImage: (if the
default background image is used, the default shadow image will be
used).
now you can use it, with this line:
self.tabBarController.tabBar.barStyle = UIBarStyleBlack;

How to apply a background image to navigation bar

I want to insert an image to the navigation bar.
My code is
UINavigationBar *navBar = self.navigationController.navigationBar;
UIImage *image = [UIImage imageNamed:#"bodyBg.png"];
[navBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
I have attached the screenshot of the current output. Is this because of the large image size?
But my desired output is
First, make your navigation bar image size 1024x44 pixels nad for retina display 2048x88 pixels.
If you have the same image for UINavigationBar on every view controller, put this to AppDelegate in method didFinishLaunchingWithOptions:
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"nav-background.png"] forBarMetrics:UIBarMetricsDefault];
// This will remove shadow in iOS6
if ([[UINavigationBar class] instancesRespondToSelector:#selector(shadowImage)]) {
[[UINavigationBar appearance] setShadowImage:[[[UIImage alloc] init] autorelease]];
}
And also I see you need custom back button, also put this in AppDelegate:
UIImage *backButtonNormal = [UIImage imageNamed:#"nav-back.png"];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
you can set the color of navigation bar same as your image use below code and you can put image name which you want to show in navigation bar
self.navigationController.navigationBar.tintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"bodyBg.png"]];
try it out with this code..
if ([navBar respondsToSelector:#selector(setBackgroundImage:forBarMetrics:)])
{
[navBar setBackgroundImage:[UIImage imageNamed:#"Nav.png"] forBarMetrics:UIBarMetricsDefault];
}
else
{
UIImageView *imageView = (UIImageView *)[navBar viewWithTag:1];//any tag
if (imageView == nil)
{
imageView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"Nav.png"]];
[navBar insertSubview:imageView atIndex:0];
[imageView release];
}
}
see my full answer from this link setting-title-for-uinavigation-bar-in-iphone
self.navigationController.navigationBar.tintColor = [UIColor clearColor];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navBar"] forBarMetrics:UIBarMetricsDefault];
I hope , it will work for u
Use UINavigationBar's setBackgroundImage: forBarMetrics: method :
[self.navigationController.navigationBar setBackgroundImage:yourImageHere forBarMetrics:UIBarMetricsDefault];
your UIImage should be of appropriate height and width. For example iphone 4 retina size would be 640*88 for portrait.
EDIT : Point here is if UIImage height is bigger say 150 pixel height it will display that much height and our UINavigationBar height is 44 pixel.
check this link for add background image in navigationbar and first you your navigationbar
image size set as navigationbar.
check this link here
i hope this code useful for you.
[myNavbar setBackgroundImage:[UIImage imageNamed: #"UINavigationBarBackground.png"]
forBarMetrics:UIBarMetricsDefault];
and also this link
Try this code it works for me:
UIView* navigationBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
UIImage * targetImage = [UIImage imageNamed:#"Header_top.png"];
UIGraphicsBeginImageContextWithOptions(navigationBGView.frame.size, NO, 0.f);
[targetImage drawInRect:CGRectMake(0.f, 0.f, navigationBGView.frame.size.width, navigationBGView.frame.size.height)];
UIImage * resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
navigationBGView.backgroundColor = [UIColor colorWithPatternImage:resultImage];
[self.navigationController.navigationBar addSubview:navigationBGView];
[self.navigationController.navigationBar setTintColor:[UIColor clearColor]];

Set NavigationBar background to a solid color

Is there any way I can set the background of the Navigation Bar of the UINavigationController to a solid color?
I know I can change the Tint color, but that still leaves me with the gradient/glass effect.
Any way I can get rid of that, and just have a plain old solid color?
The following code also results in solid color of navigation bar:
[[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundColor:[UIColor redColor]];
I think you have to subclass UINavigationBar and override -(void)drawRect:(CGRect)rect:
UIColor *colorFlat = /* any UIColor*/
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [colorFlat CGColor]);
CGContextFillRect(context, rect);
I used to override drawRect method and fill color; but after iOS7 upgrade it causes some problems on UINavigationBar. If you write your own drawrect method, even if you call [super drawRect], it changes the bar's dimension and you end up with a navigationBar with 44 pixels height. The status bar is left empty.
To get a solid colored navigationBar, I used an image as background image (any small solid colored image will do since you are stretching it) and added this lines inside the initWithFrame method of the UINavigationBar subclass:
[self setBackgroundColor:[UIColor clearColor]]
[[UINavigationBar appearance] setBackgroundImage:[[UIImage imageNamed:#"bgimage.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(5, 5, 5, 5) resizingMode:UIImageResizingModeStretch] forBarMetrics:UIBarMetricsDefault];
The following code worked for me:
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBarTintColor:[UIColor greenColor]];
self.navigationController.navigationBar.translucent = NO;
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
Create a CustomUIViewController that extends UIViewController and override viewDidLoad to something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.view.backgroundColor = [UIColor colorWithRed: 0.0 green: 0.0 blue: 1.0 alpha: 1.0];
}
After that, use your CustomUIViewController in your controllers.
Credits

Changing Tint / Background color of UITabBar

The UINavigationBar and UISearchBar both have a tintColor property that allows you to change the tint color (surprising, I know) of both of those items. I want to do the same thing to the UITabBar in my application, but have found now way to change it from the default black color. Any ideas?
iOS 5 has added some new appearance methods for customising the look of most UI elements.
You can target every instance of a UITabBar in your app by using the appearance proxy.
For iOS 5 + 6:
[[UITabBar appearance] setTintColor:[UIColor redColor]];
For iOS 7 and above, please use the following:
[[UITabBar appearance] setBarTintColor:[UIColor redColor]];
Using the appearance proxy will change any tab bar instance throughout the app. For a specific instance, use one of the new properties on that class:
UIColor *tintColor; // iOS 5+6
UIColor *barTintColor; // iOS 7+
UIColor *selectedImageTintColor;
UIImage *backgroundImage;
UIImage *selectionIndicatorImage;
I have been able to make it work by subclassing a UITabBarController and using private classes:
#interface UITabBarController (private)
- (UITabBar *)tabBar;
#end
#implementation CustomUITabBarController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0.0, 0.0, self.view.bounds.size.width, 48);
UIView *v = [[UIView alloc] initWithFrame:frame];
[v setBackgroundColor:kMainColor];
[v setAlpha:0.5];
[[self tabBar] addSubview:v];
[v release];
}
#end
I have an addendum to the final answer. While the essential scheme is correct, the trick of using a partially transparent color can be improved upon. I assume that it's only for letting the default gradient to show through. Oh, also, the height of the TabBar is 49 pixels rather than 48, at least in OS 3.
So, if you have a appropriate 1 x 49 image with a gradient, this is the version of viewDidLoad you should use:
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0, 0, 480, 49);
UIView *v = [[UIView alloc] initWithFrame:frame];
UIImage *i = [UIImage imageNamed:#"GO-21-TabBarColorx49.png"];
UIColor *c = [[UIColor alloc] initWithPatternImage:i];
v.backgroundColor = c;
[c release];
[[self tabBar] addSubview:v];
[v release];
}
When you just use addSubview your buttons will lose clickability, so instead of
[[self tabBar] addSubview:v];
use:
[[self tabBar] insertSubview:v atIndex:0];
There is no simple way to do this, you basically need to subclass UITabBar and implement custom drawing to do what you want. It is quite a bit of work for the effect, but it may be worth it. I recommend filing a bug with Apple to get it added to a future iPhone SDK.
Following is the perfect solution for this. This works fine with me for iOS5 and iOS4.
//---- For providing background image to tabbar
UITabBar *tabBar = [tabBarController tabBar];
if ([tabBar respondsToSelector:#selector(setBackgroundImage:)]) {
// ios 5 code here
[tabBar setBackgroundImage:[UIImage imageNamed:#"image.png"]];
}
else {
// ios 4 code here
CGRect frame = CGRectMake(0, 0, 480, 49);
UIView *tabbg_view = [[UIView alloc] initWithFrame:frame];
UIImage *tabbag_image = [UIImage imageNamed:#"image.png"];
UIColor *tabbg_color = [[UIColor alloc] initWithPatternImage:tabbag_image];
tabbg_view.backgroundColor = tabbg_color;
[tabBar insertSubview:tabbg_view atIndex:0];
}
On iOS 7:
[[UITabBar appearance] setBarTintColor:[UIColor colorWithRed:(38.0/255.0) green:(38.0/255.0) blue:(38.0/255.0) alpha:1.0]];
I also recommend setting first depending on your visual desires:
[[UITabBar appearance] setBarStyle:UIBarStyleBlack];
The bar style puts a subtle separator between your view content and your tab bar.
[[self tabBar] insertSubview:v atIndex:0];
works perfectly for me.
for me its very simple to change the color of Tabbar like :-
[self.TabBarController.tabBar setTintColor:[UIColor colorWithRed:0.1294 green:0.5686 blue:0.8353 alpha:1.0]];
[self.TabBarController.tabBar setTintColor:[UIColor "YOUR COLOR"];
Try this!!!
[[UITabBar appearance] setTintColor:[UIColor redColor]];
[[UITabBar appearance] setBarTintColor:[UIColor yellowColor]];
for just background color
Tabbarcontroller.tabBar.barTintColor=[UIColor redcolour];
or this in App Delegate
[[UITabBar appearance] setBackgroundColor:[UIColor blackColor]];
for changing color of unselect icons of tabbar
For iOS 10:
// this code need to be placed on home page of tabbar
for(UITabBarItem *item in self.tabBarController.tabBar.items) {
item.image = [item.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
Above iOS 10:
// this need to be in appdelegate didFinishLaunchingWithOptions
[[UITabBar appearance] setUnselectedItemTintColor:[UIColor blackColor]];
There are some good ideas in the existing answers, many work slightly differently and what you choose will also depend on which devices you target and what kind of look you're aiming to achieve. UITabBar is notoriously unintuitive when it come to customizing its appearance, but here are a few more tricks that may help:
1). If you're looking to get rid of the glossy overlay for a more flat look do:
tabBar.backgroundColor = [UIColor darkGrayColor]; // this will be your background
[tabBar.subviews[0] removeFromSuperview]; // this gets rid of gloss
2). To set custom images to the tabBar buttons do something like:
for (UITabBarItem *item in tabBar.items){
[item setFinishedSelectedImage:selected withFinishedUnselectedImage:unselected];
[item setImageInsets:UIEdgeInsetsMake(6, 0, -6, 0)];
}
Where selected and unselected are UIImage objects of your choice. If you'd like them to be a flat colour, the simplest solution I found is to create a UIView with the desired backgroundColor and then just render it into a UIImage with the help of QuartzCore. I use the following method in a category on UIView to get a UIImage with the view's contents:
- (UIImage *)getImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [[UIScreen mainScreen]scale]);
[[self layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
3) Finally, you may want to customize the styling of the buttons' titles. Do:
for (UITabBarItem *item in tabBar.items){
[item setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor redColor], UITextAttributeTextColor,
[UIColor whiteColor], UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(0, 1)], UITextAttributeTextShadowOffset,
[UIFont boldSystemFontOfSize:18], UITextAttributeFont,
nil] forState:UIControlStateNormal];
}
This lets you do some adjustments, but still quite limited. Particularly, you cannot freely modify where the text is placed within the button, and cannot have different colours for selected/unselected buttons. If you want to do more specific text layout, just set UITextAttributeTextColor to be clear and add your text into the selected and unselected images from part (2).
[v setBackgroundColor ColorwithRed: Green: Blue: ];
Another solution (which is a hack) is to set the alpha on the tabBarController to 0.01 so that it is virtually invisible yet still clickable. Then set a an ImageView control on the bottom of the MainWindow nib with your custom tabbar image underneath the alpha'ed tabBarCOntroller. Then swap the images, change colors or hightlight when the tabbarcontroller switches views.
However, you lose the '...more' and customize functionality.
Hi There am using iOS SDK 4 and i was able to solve this issue with just two lines of code and it's goes like this
tBar.backgroundColor = [UIColor clearColor];
tBar.backgroundImage = [UIImage imageNamed:#"your-png-image.png"];
Hope this helps!
if ([tabBar respondsToSelector:#selector(setBackgroundImage:)]) {
// ios 5 code here
[tabBar setBackgroundImage:[UIImage imageNamed:#"image.png"]];
}
else {
// ios 4 code here
CGRect frame = CGRectMake(0, 0, 480, 49);
UIView *tabbg_view = [[UIView alloc] initWithFrame:frame];
UIImage *tabbag_image = [UIImage imageNamed:#"image.png"];
UIColor *tabbg_color = [[UIColor alloc] initWithPatternImage:tabbag_image];
tabbg_view.backgroundColor = tabbg_color;
[tabBar insertSubview:tabbg_view atIndex:0];
}
Swift 3.0 answer: (from Vaibhav Gaikwad)
For changing color of unselect icons of tabbar:
if #available(iOS 10.0, *) {
UITabBar.appearance().unselectedItemTintColor = UIColor.white
} else {
// Fallback on earlier versions
for item in self.tabBar.items! {
item.image = item.image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
}
}
For changing text color only:
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.white], for: .normal)
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red, for: .selected)
Swift 3 using appearance from your AppDelegate do the following:
UITabBar.appearance().barTintColor = your_color

Resources