Add UINavigationBar Shadow Application Wide? - iphone

There are a few tutorial about showing how to add a shadow to a UINavigation bar, but is there any method which would best suit adding this shadow application wide, rather than in a single instance?
Or is my only option to simply have a sub-classed nab bar in every single view of my application? Thought there might be a quicker, easier way than doing that?
Thanks.

Create a category of UINavigationBar called UINavigationBar+dropshadow.m and put this in the file
#import <QuartzCore/QuartzCore.h>
#interface UINavigationBar (dropshadow)
-(void) applyDefaultStyle;
#end
#implementation UINavigationBar (dropshadow)
-(void)willMoveToWindow:(UIWindow *)newWindow{
[super willMoveToWindow:newWindow];
[self applyDefaultStyle];
}
- (void)applyDefaultStyle {
// add the drop shadow
self.layer.shadowColor = [[UIColor blackColor] CGColor];
self.layer.shadowOffset = CGSizeMake(0.0, 3.0);
self.layer.shadowOpacity = 0.25;
self.layer.shouldRasterize = YES;
}
#end

If you're working with iOS6, you can use the Appearance proxy to do that.
Here's the Apple Class Reference: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAppearance_Protocol/Reference/Reference.html
EDIT 1 Fixed required iOS version (was mistakenly iOS5 previously)
EDIT 2
See this SO question: Appearance proxy - setShadowImage alternative for iOS 5? for a code snippet

Related

Better to customize UINavigationBar with image or programmatically?

I know that there are two distinct ways to customize a UINavigationBar: you can either set the background image to some custom png, or you could customize the bar's appearance in code, programmatically. If my aim is to support iOS 4,5,6 does it make sense to try to customize the bar's appearance through code?
I essentially want a navigationbar without any gradience, a solid color, rounded corners, and an extremely thin shadow line. I would post an image below but I need at least 10 reputation points :(
I've started with the following code to address the no gradience and solid color issues, and I've placed this in the .m file of my rootviewcontroller before the #implementation of the class itself, but to no avail:
#implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
UIColor *color = [UIColor blueColor];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColor(context, CGColorGetComponents( [color CGColor]));
CGContextFillRect(context, rect);
}
#end
I also have implemented this code to round out the corners, which works:
CALayer *capa = [self.navigationController navigationBar].layer;
[capa setShadowColor: [[UIColor blackColor] CGColor]];
[capa setShadowOpacity:0.85f];
[capa setShadowOffset: CGSizeMake(0.0f, 1.5f)];
[capa setShadowRadius:2.0f];
[capa setShouldRasterize:YES];
//Round
CGRect bounds = capa.bounds;
bounds.size.height += 10.0f; //I'm reserving enough room for the shadow
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight)
cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.path = maskPath.CGPath;
[capa addSublayer:maskLayer];
capa.mask = maskLayer;
Any help on this matter would be greatly appreciated!
If you want to target iOS < 5 then the UIAppearance won't help you because it is supported only for iOS >= 5.
So in my opinion, using a png file for the navigation bar's background is faster and maybe safer. Depending on your desired result you can do it from code and also make it faster, just create a BaseViewController that will handle the navigation bar's appearance (background, title, buttons etc) and all your custom view controllers can inherit from this BaseViewController, but this implementation in some cases can has it's own drawbacks since you can't inherit from multiple classes in iOS, and I'm afraid that you will find out this a little bit late when you will get to a point when you will want to have features from a view controller that doesn't inherit from the BaseViewController.
On the other hand, creating the color and the graphics from code will probably raise issues from the beloved designers who will want 1px left/up/right/down/diagonal/etc, and in this way you will have headaches (happen to me).
If you are targeting iOS >=5 then UIAppearance is your friend.
So in conclusion, if you are targeting iOS >= 5 use UIAppearance if not, if you have a more complex (gradient, lines, strange colors) UI for your nav bar use png, if you have simple (one flat color) UI for nav bar, you can do it from code with no problems.
The appearance proxy of the UINavigationBar is there to set the default for ALL UINavigationBars if you want ALL of the bars to change then do it programmatically, if you want only 1 to change then do it in the storyboard both methods should have the same outcome for the appearance of your NavigationBar
The color/shadow should be with in the image, but be mindful of the fact that you shouldn't change the height of the navigation bar...
if you are able to have the image have the rounded corners and the shadow baked in
if you are not you will have to do it in code by using your code above
That is a simple method... a more advanced method would be creating a UINavigationBar item in your storyboard with an associated IBOutlet, setting an outlet to that item, set all the properties from with in the storyboard like the background image, then with in the viewDidLoad method set the IBOutlet of the UINavigationBar to the UINavigationBar of the UINavigationController of the UIViewController that you are loading. Also, you can round the corners of the UINavigationBar here if you desire.

How to create a customized rounded UiView and UIButton like MobilePASS?

I want to create a similar UIView with rounded corner and UIButton just like this app.
Can I implement this on Interface Builder?
You can round the corners and set a border in code, just make sure you have QuartzCore framework included.
-(void) viewDidLoad {
[super viewDidLoad];
self.welcomeView.layer.cornerRadius = 5;
self.welcomeView.layer.borderWidth = 2;
self.welcomeView.layer.borderColor = [[UIColor whiteColor] CGColor];
}
Then just lay out your views and setup your outlets in IB. That should get you going, lots of cool stuff in Quartz.
Here is a link to the API reference http://developer.apple.com/library/mac/ipad/#documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40004500
Take a look at this tutorial by Ray Wenderlich.

How can I get a 'matte' color on a UINavigationBar?

How can I get a matte color on a UINavigationBar instead of the shiny look?
[self.navigationController.navigationBar setTintColor:[UIColor blackColor]];
There's no built-in way to do this. Using tintColor will always get you the default "shiny" look. The alternative is to draw the bar yourself, using the technique described here, to get the look you want.
My simple way using category UINavigationBar:
#implementation UINavigationBar (UINavigationBarWithoutShiny)
- (void)drawRect:(CGRect)rect {}
#end
after this i can use just background color of UINavigationBar view:
self.navigationController.navigationBar.backgroundColor = [UIColor greenColor];

How can I draw a rounded rectangle Label or View?

I need to draw a rounded rectangle bar in my iOS application, but without using a background image. Is there any way to make a rounded rectangle view or label?
In addition to the other answer(s), don't forget to set the masksToBounds property.
#import <QuartzCore/QuartzCore.h>
label.layer.cornerRadius = 5.0;
label.layer.masksToBounds = YES;
Alternative if you're using the UI designer (Storyboard or nib file) you can set a User Defined Runtime Attribute.
Click on the view you want to have rounded corners, click Show the Identity Inspector (3rd tab, top right).
Then click the + in User Defined Runtime Attributes and enter the following:
Key Path: layer.cornerRadius
Type: Number
Value: whatever number, e.g. 5
Add Quartz core Framework ..
#import <QuartzCore/QuartzCore.h>
Then Set corner radius,
yourView_LabelName.layer.cornerRadius = 10.0;
It may be useful for you.
Step1 :add the quartzcore framework to your project frameworks.
In which file you want to write this code there, you have to use this.
#import <QuartzCore/QuartzCore.h>
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 50, 30)];
myLabel.text = #"text";
myLabel.layer.cornerRadius =8.0;
[self.view addSubview:myLabel];

How do I subclass UITextField and override drawPlaceholderInRect to change Placeholder color

I have a 3 UITextField with placeholder text set. On one of the UITextField I want the placeholder text to be red.
Now after googling it seems the best way to do this is to subclass UITextField and override drawPlaceholderInRect.
How do I go about subclassing and overriding drawPlaceholderInRect? I've not found any code examples or tutorials on this and I'm new to objective-c and iOS development so finding it tricky to work it out.
Answer:
Created a new objective-c class called CustomUITextFieldPlaceholder which subclassed UITextField. In CustomUITextFieldPlaceholder.m put the following code
#implementation CustomUITextFieldPlaceholder
- (void)drawPlaceholderInRect:(CGRect)rect {
// Set colour and font size of placeholder text
[[UIColor redColor] setFill];
[[self placeholder] drawInRect:rect withFont:[UIFont systemFontOfSize:12]];
}
#end
To implement the above in your project
#import "CustomUITextFieldPlaceholder.h"
and
IBOutlet CustomUITextFieldPlaceHolder *txtName;
Note: This works and I believe is correct practice, however I have not fully tested it. Hope this example helps others in my situation.
Edit:
Changed
[[UIColor redColor] setFill];
for
[[UIColor colorWithRed:255.0 green:0.0 blue:0.0 alpha:0.7] setFill];
So that I could set the opacity to 70% to mimic default placeholder.
To answer you specific question, this is how subclassing works:
// CustomTextField.h
#interface CustomTextField : UITextField {
}
#end
Here's how to override the method:
#implementation
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
return CGRectMake(x,y,width,height);
}
#end
However I don't think that's the method you want to override. I think this is what you're looking for:
#implementation
- (void)drawPlaceholderInRect:(CGRect)rect {
// Your drawing code.
}
#end
Subclassing won't change the color. I have put forward a work around here.
UITextField placeholder font color white iOS 5?
[yourTextfield setValue:[UIColor colorWithRed:62.0/255.0f green:62.0/255.0f blue:62./255.0f alpha:1.0f] forKeyPath:#"_placeholderLabel.textColor"];
I guess this would be helpful