I'd like to draw a simple inset line in Interface Builder to separate some items in a list and make the UI a bit more tidy. I don't see any "line" or similar objects in the objects library and can't seem to find any drawing commands in Interface builder.
I use a very narrow UIView with backgroundColor set to the appropriate color.
There are no lines in the iPhone UI library. This functionality on Max OS X was supplied by NSBox, but on the iPhone there is no corresponding UI element.
If you're afraid a UIView might affect performance, you can draw a line in code using CoreGraphics' CAShapeLayers.
Every UIView has a CALayer, so draw the line and add it to the views CALayer.
You can do this either in a custom UIView's drawRect or in your view controller:
(Make sure to add Quartz framework to your project)
UIBezierPath *linePath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0,self.view.frame.size.width, 1)];
//shape layer for the line
CAShapeLayer *line = [CAShapeLayer layer];
line.path = [linePath CGPath];
line.fillColor = [[UIColor blackColor] CGColor];
line.frame = CGRectMake(xPosition, yPosition, self.view.frame.size.width,1);
[self.view.layer addSublayer:line];
In place of view, why not just use a label and set the appropriate background color?
I used a view and made it narrow & changed the color to make it look like a line. But my issue is I am using the line on a vertical scrollview and the lines also get scrolled.
Interface Builder does not allow you to draw the shadows essential for an inset line. If you work with Photoshop you know this.
The following code will draw an "inset" if the line is in front of a white/beige Background.
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 1.0f)];
line.backgroundColor = [UIColor colorWithRed:(200.0f/255.0f) green:(200.0f/255.0f) blue:(200.0f/255.0f) alpha:1.0f];
line.layer.shadowColor = [UIColor darkGrayColor].CGColor;
line.layer.shadowOffset = CGSizeMake(0.0f, 1.0f);
line.layer.shadowRadius = 0.5f;
line.layer.shadowOpacity = 0.4f;
line.layer.masksToBounds =NO;
[Background addSubview:line];
Remember to import < QuartzCore/QuartzCore.h>.
As an alliterative - in Interface Builder, add a view who's height is set to 2 points. Wire up a IBOutlet to that view and set its layer border color and width:
self.mySeparatorLine.layer.borderWidth = 1.0f;
self.mySeparatorLine.layer.borderColor = [UIColor lightGrayColor].CGColor;
You can use Progress View as an option for a horizontal line. Just change the tint color and progress to 1 which is 100%.
Related
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.
i am developing one application in which i want to create shadow effect similar to shown in below image at bottom uitableviewcell.
How can i do that?any tutorial or sample code? I have checked http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html,
http://www.touchthatfruit.com/?tag=uitableview
and some other ones.but they have shadow at bottom of uitableview with same height.and how to
add shadow at side borders of each section containing the date(not the entire tableview).I can create the dropdown shadow at bottom.but what about side borders of last uitableview cell of each section.and one way is creating the image and setting it as background of tableviewcell.But how to resize the image and will it look proper because each section has dynamic number of entries.one section only have 1 entry and other may contain 15 or more entries.(here image is for entire section which contains date).i can have seperate image for only last tableviewcell of each section.This is i know.but is there any better approach or do it programatically?
You can refer the following link for shadow effect in uitableview that will help you
try this
A fundamental piece of a view is it's layer which is a CALayer. You can access it through the layer property of a view:
myView.layer
In the documentation CALayers have several properties that control the shadow. You should be able to tell the navigation bar's layer to cast a shadow. Along with the layers of any other content that you want to cast a shadow.
myView.layer.shadowOffset
myView.layer.shadowRadius
You will need to be sure to add the QuartzCore framework to your project to access this property
Will each section always be the same size? If so why don't you subclass the UITableViewCell to draw the notebook like item with the drop shadow included?
You can also add a transparent UIImageView over the UITableView to get the darkened corners.
EDIT:
This effect is a bit tricky, you're going to want to look into how to use UIBezierPaths (http://developer.apple.com/library/IOS/#documentation/UIKit/Reference/UIBezierPath_class/Reference/Reference.html).
The top portion can be an image (the rings and tab effect). You can then draw the rest of the cell in the drawRect function. (This more efficient than using the shadow properties in layer which is important in a UITableViewCell).
You'll want to override your UITableViewCell class and implement a custom drawRect: function.
Here's some code to get you started:
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
/* Draw top image here */
//now draw the background of the cell.
UIBezierPath *path1 = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 320, 50)];
[[UIColor grayColor] set];
[path1 fill];
UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:CGRectMake(0, 52, 320, 50)];
[[UIColor whiteColor] set];
[path2 fill];
UIBezierPath *path3 = [UIBezierPath bezierPathWithRect:CGRectMake(0, 104, 320, 50)];
[[UIColor grayColor] set];
[path3 fill];
UIBezierPath *path4 = [UIBezierPath bezierPathWithRect:CGRectMake(0, 156, 320, 50)];
[[UIColor whiteColor] set];
[path4 fill];
//and so on...
//Let's draw the shadow behind the last portion of the cell.
UIBezierPath *shadow = [UIBezierPath bezierPathWithRect:CGRectMake(0, 208, 320, 52)];
[[UIColor darkGrayColor] set];
[shadow fill];
//Finally, here's the last cell with a curved bottom
UIBezierPath *path5 = [UIBezierPath bezierPath];
[path5 moveToPoint:CGPointMake(0, 208)];
[path5 addLineToPoint:CGPointMake(320, 208)];
[path5 addLineToPoint:CGPointMake(320, 258)];
[path5 addCurveToPoint:CGPointMake(0, 258) controlPoint1:CGPointMake(160, 254) controlPoint2:CGPointMake(160, 254)];
[[UIColor grayColor] set];
[path5 fill];
}
The code isn't quite drag and drop, You still need to add the white lines, fix some sizes, and tweak the last cell and shadow to be just right. But it should be enough to get you started.
Cheers!
Take a look at my answer to a similar question, this one may be a possible solution to your problem! By altering the shadow path you should be able to achieve the desired shadow effect!
This can be achieved using the bezierpath:Check the URL for getting various shadow effects:http://nachbaur.com/blog/fun-shadow-effects-using-custom-calayer-shadowpaths
I've got a UIView container with a table view in it, whose cells contain images and buttons.
I want to add a shadow to the outter-most container but when I do, I found shadows are also added to all the images and buttons. How can I only add shadow to the layer itself without its sublayers?
code:
listContainer.layer.shadowColor = [UIColor blackColor].CGColor;
listContainer.layer.shadowOffset = CGSizeMake(3, 0);
listContainer.layer.shadowOpacity = .8;
listContainer.layer.borderColor = [UIColor blackColor].CGColor;
Thanks!
Have you tried the shadowPath property of your layer?
listContainer.layer.shadowPath = [UIBezierPath bezierPathWithRect:listContainer.bounds.CGPath];
I had this problem once and the issue was that the layers background color was transparent.
So if you have a UIView, or CALayer, and you are trying to set shadows on it, make sure that there is a background color to prevent shadows from being applied to the sublayers.
I have a UIView whose color is black and opacity is 0.9 or something like that. What I want to do is to fill the UIView with black portion, but a specified rectangular area should not get black. i.e. that particular rectangular area remains with clear color...
Any kind of help will be appreciated.
regards,
Imran
You can subclass UIView and override - (void)drawRect:(CGRect)rect
And do something of the following (untested, but used something similar myself);
- (void)drawRect:(CGRect)rect {
// fill the whole UIView with a color
[[UIColor colorWithRed:1 green:1 blue:1 0.9] setFill];
UIRectFill( rect );
// draw a rect
CGRect rectIntersection = CGRectIntersection(theRectIWantToDrawIn, rect);
[[UIColor clearColor] setFill];
UIRectFill( rectIntersection );
}
The code above draws a black view with a simulated clearColor hole in it at a certain position. You could, of course, alter this behavior to your liking.
This is quite fast.
UPDATE: Do note that I set the UIView on which I want to draw the rect to UIClear color (I added it to a xib and set those properties there) and unchecked 'Opaque'. That should make the hole see-through.
UPDATE 2: My answer was based on this answer (credit where credit is due): iPhone - Draw transparent rectangle on UIView to reveal view beneath
Add another view (subview) to that area. And set its to your desired color. Thats the easy solution with your current requirements.
Or you can use some quartz core functions.
You can create a small UIView in the main view by custom and set background clear color
UIView *View1 = [[UIView alloc] initWithFrame:CGRectMake(128.0f, 50.0f, 34.0f, 34.0f)];
[View1 setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:View1];
[View1 release];
I am trying to add round corner to UISearchBar at the top-left and top-right corners.
However, I found the mask layer doesn't work on UISearchBar, no matter how I set it.
Here is my code
// UIView* bar = [searchBar_.subviews objectAtIndex:0]; // try to add mask to background view but also failed
UIView* bar = searchBar_;
CGRect toolbarBounds = bar.bounds;
CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect: toolbarBounds
byRoundingCorners:UIRectCornerTopLeft
cornerRadii:CGSizeMake(5.0f, 5.0f)];
[maskLayer setPath:[path CGPath]];
[maskLayer setFillColor:[[UIColor greenColor] CGColor]];
bar.layer.masksToBounds = YES;
bar.layer.mask = maskLayer;
I have also tried the "Clip subviews", but it doesn't work either.
Then I try something more, I just set the background view (subview 0) hidden. To mu surprise, it is still visible.
Is there any magic in the UISearchBar?
The mask does work on UIToolbar.
Your problem could be related to how the mask property is implemented. It will not work if you add a mask layer to a layer which is already part of a hierarchy. The docs for CALayer say:
When setting the mask to a new layer, the new layer’s superlayer must first be set to nil, otherwise the behavior is undefined.
You'll have to remove the search bar from its superview before adding the mask layer. Wrap your last line like so:
UIView *superview = [bar superview];
[bar removeFromSuperview];
bar.layer.mask = maskLayer;
[superview addSubview:bar];
You can also use removeFromSuperlayer and addSublayer: if you prefer. Also, if your search bar isn't the topmost view in your hierarchy, make sure to find out where it is and put it back in the right place using insertSubview:atIndex: or one of the similar methods.