draw borderline around UITableView section in ios 7 - ios

I have an issue regarding the section border. I have a UITableView and it is of type Grouped. I am trying to draw the border around the each section of the tableview. I am getting the section frame using the below code. Could please tell me how to draw the border around the UITableView section.
CGRect rect = [groupsTableView rectForSection:indexPath.section];
NSLog(#"%f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);

I will recommend that you make a new TableView Cell and inside this newTableViewCell, load all the cells in section 2 then give border to newTableViewCell.
but if you don't wanna do that then you can use this code :
#property(strong,nonatomic) CAShapeLayer* borderPath;
-(void)viewDidLayoutSubviews{
[_borderPath removeFromSuperlayer];
UIView *viewToGiveBorder = [[UIView alloc]initWithFrame:sectionView.frame];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:viewToGiveBorder.bounds byRoundingCorners:(UIRectCornerAllCorners) cornerRadii:CGSizeMake(5.0, 5.0)];
//apply path to shapelayer
_borderPath= [CAShapeLayer layer];
_borderPath.path = path.CGPath;
[_borderPath setFillColor:[UIColor clearColor].CGColor];
[_borderPath setStrokeColor:[UIColor colorWithRed: 0 green: 0 blue: 0].CGColor];
_borderPath.frame=sectionView.frame;
//add shape layer to view's layer
[[self.view layer] addSublayer:_borderPath];
}

Related

How to add a circleView progress to an UIView expanding to all UIView?

I have setup a UIView using constraints in a storyboard, and I want to add a circle progress to this view using CAShapeLayer with a UIBezierPath.
I have added this correctly, but the circle isn't expanded to all the view. i call this in my viewDidLoad function. My view has constraints to asjust height top-x view and width.
- (void)viewDidLoad {
[super viewDidLoad];
CAShapeLayer *borderLayer = [CAShapeLayer layer];
borderLayer.fillColor = [UIColor whiteColor].CGColor;
CGFloat lineWidth = 4;
CGRect rect = CGRectMake(lineWidth+lineWidth/2, lineWidth+lineWidth/2, self.myView.bounds.size.width/2, self.myView.bounds.size.height/2);
borderLayer.path = [UIBezierPath bezierPathWithOvalInRect:rect].CGPath;
borderLayer.strokeColor = [[UIColor redColor] CGColor];
borderLayer.lineWidth = lineWidth;
[borderLayer setFillColor:[UIColor clearColor].CGColor];
[self.myView.layer addSublayer:borderLayer];
}
The circle progress isn't resized to the UIView, and it is shown like this:
How can I draw this occupying the whole UIView like this:
1 - Your view's frame will not have been set yet in viewDidLoad. You need to move this code into viewDidLayoutSubviews or later in the view controller's lifecycle.
Related Question:
Why am I having to manually set my view's frame in viewDidLoad?
Apple Docs on view controller lifecycle:
https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/WorkWithViewControllers.html#//apple_ref/doc/uid/TP40015214-CH6-SW1
2 - Change this:
CGRect rect = CGRectMake(lineWidth+lineWidth/2, lineWidth+lineWidth/2, self.myView.bounds.size.width/2, self.myView.bounds.size.height/2);
to this:
CGRect rect = CGRectMake(lineWidth/2, lineWidth/2, self.myView.bounds.size.width - lineWidth, self.myView.bounds.size.height - lineWidth);
Result (I used slightly different lineWidth and view size for my testing):

How to add top corners, top border and top shadow to a UIView at the same time

I need to add several kinds of effects on a UIView with rounding its top left and top right corners, white border and dark shadow on its rounded corner curve like the picture below:
I created a MSHTablePaneCell class inherited from UIView and then overrided its drawRect method:
static const CGFloat kCornerRadius = 15;
#implementation MSHTablePaneCell ()
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:(UIRectCornerTopLeft |UIRectCornerTopRight) cornerRadii:CGSizeMake(kCornerRadius, kCornerRadius)];
// 1. mask round corner
CAShapeLayer *roundLayer = [CAShapeLayer layer];
roundLayer.path = path.CGPath;
roundLayer.frame = self.bounds;
// roundLayer.cornerRadius = 10.0;
self.layer.mask = roundLayer;
// 2. add border to round corner curve
UIBezierPath *topCurvepath = [UIBezierPath bezierPath];
[topCurvepath moveToPoint:CGPointMake(0, kCornerRadius)];
[topCurvepath addQuadCurveToPoint:CGPointMake(kCornerRadius, 0) controlPoint:CGPointMake(0, 0)];
[topCurvepath addLineToPoint:CGPointMake(CGRectGetWidth(self.frame)-kCornerRadius, 0)];
[topCurvepath addQuadCurveToPoint:CGPointMake(CGRectGetWidth(self.frame), kCornerRadius) controlPoint:CGPointMake(CGRectGetWidth(self.frame), 0)];
CAShapeLayer *topBorderLayer = [CAShapeLayer layer];
topBorderLayer.lineWidth = 4.0;
topBorderLayer.borderColor = [UIColor redColor].CGColor;
topBorderLayer.path = topCurvepath.CGPath;
[self.contentView.layer addSublayer:topBorderLayer];
}
#end
However, with code above, I just got the final picture like below:
No matter which property I set, the topCurvePath just displayed with black background color, how I can fix this problem? Thanks in advance~
topBorderLayer.fillColor = [UIColor yourColor].CGColor

How to remove black edge on UIImageView with rounded corners and a border width?

I have the following code to make the UIImageView in each of my UITableView's cells have rounded corners:
- (void)awakeFromNib
{
// Rounded corners.
[[cellImage layer] setCornerRadius:([cellImage frame].size.height / 2)];
[[cellImage layer] setMasksToBounds:YES];
[[cellImage layer] setBorderColor:[[UIColor whiteColor] CGColor]];
[[cellImage layer] setBorderWidth:3]; // Trouble!
}
I want the images to have a bit of a gap between them, and figured I could make use of the border width to make that happen. Below is an image of what actually happened:
It's that faint black border that I want to know how to get rid of. I'd like to think there's a way of doing it using border width. If not, the best approach might be just to resize the image itself and just set the border width to be 0.
Rather than using corner radius, you can create bezier path for the mask, create a shape layer for that path, and then specify that shape layer for the image view's layer's mask:
CGFloat margin = 3.0;
CGRect rect = CGRectInset(imageView.bounds, margin, margin);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(imageView.bounds.size.width/2, imageView.bounds.size.height/2) radius:radius startAngle:0 endAngle:M_PI*2 clockwise:NO];
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = path.CGPath;
imageView.layer.mask = mask;
What you are doing is, you are clipping the profile image and the border together, which is making the cell's profile image extending through the border.
You are missing this line:-
cellImage.clipsToBounds = YES;

Setting CALayer maskToBounds causing layer to disappear

I am trying to create a circle which is filled depending upon a certain percentage. Here is pic of the effect I am going for:
I have a UIView and to this I add a CAShapeLayer which draws the circle. I am then creating another UIShapeLayer as a square to match the UIView containing the circle. Then setting the height of this depending on the figure. So if the square is 100px high and the value is 10% then I set the square to 10px so that it fills 10% of circle.
The image below shows 50% of the circle being filled. As you can see it covers the UIView as well as the circle. However when I try to set the CAShapeLayer to mask to bounds ( circle.maskToBounds) the circle complete disappears along with the square that I am adding as it's subview.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
[self drawCircleInView:view];
[self.view addSubview:view];
}
- (void)drawCircleInView:(UIView *)v
{
// Set up the shape of the circle
int radius = v.frame.size.height / 2;
CAShapeLayer *circle = [CAShapeLayer layer];
// Make a circular shape
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2*radius, 2*radius)
cornerRadius:radius].CGPath;
// Center the shape in self.view
circle.position = CGPointMake(CGRectGetMidX(v.bounds)-radius,
CGRectGetMidY(v.bounds)-radius);
// Configure the apperence of the circle
circle.fillColor = [UIColor blueColor].CGColor;
circle.strokeColor = [UIColor clearColor].CGColor;
circle.lineWidth = 5;
circle.masksToBounds = YES; // HERE IS THE LINE OF CODE THAT MAKES THE CIRCLE DISAPPEAR
CAShapeLayer *sublayer = [CAShapeLayer layer];
sublayer.backgroundColor = [UIColor orangeColor].CGColor;
sublayer.opacity = .5f;
sublayer.frame = CGRectMake(0, 100, 200, 100);
[circle addSublayer:sublayer];
// Add to parent layer
[v.layer addSublayer:circle];
}
I am wondering why setting circle.masksToBounds = YES is making the circle and the sublayer disappear completely. My understanding is that by setting this it should only show the sublayer over the circle.
Many thanks in advance.
Try this:
- (void)drawCircleInView:(UIView *)v {
// Set up the shape of the circle
CGSize size = v.bounds.size;
CALayer *layer = [CALayer layer];
layer.frame = v.bounds;
layer.backgroundColor = [UIColor blueColor].CGColor;
CALayer *sublayer = [CALayer layer];
sublayer.frame = CGRectMake(0, size.height/2, size.width, size.height/2);
sublayer.backgroundColor = [UIColor orangeColor].CGColor;
sublayer.opacity = .5f;
CAShapeLayer *mask = [CAShapeLayer layer];
mask.frame = v.bounds;
mask.path = [UIBezierPath bezierPathWithOvalInRect:v.bounds].CGPath;
mask.fillColor = [UIColor blackColor].CGColor;
mask.strokeColor = [UIColor clearColor].CGColor;
[layer addSublayer:sublayer];
[layer setMask:mask];
// Add to parent layer
[v.layer addSublayer:layer];
}
maskToBounds is "to bounds" you are not setting bounds nor frame.
It's not necessary, but you'd better to set frame of CAShapeLayer, to prevent unnecessary confusion.
bounds is rectangle, not CAShapeLayer's shape. Use mask layer to mask by shape instead.
circle and sublayer is not need to be CAShapeLayer because it will be masked by shaped mask layer.
To achieve this use a square image with its center circle as transparent. like this image
How to use this image for this effect -
Add a square layer (with lighter color/ or non fill color) first. above that add a layer with the fill color with sane rect. and above all place this image. and change the frame of middle layer that has the fill color to achieve desired effect

Round some corners of UIView and round the view’s layer’s border too

I am trying to round the bottom two corners of a UIView, and have the layer’s border show up rounded as well. I am currently doing:
UIRectCorners corners = UIRectCornerBottomLeft | UIRectCornerBottomRight;
CGSize radii = CGSizeMake(kThisViewCornerRadius, kThisViewCornerRadius);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:myView.bounds
byRoundingCorners:corners
cornerRadii:radii];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
[maskLayer setPath:path.CGPath];
myView.layer.mask = maskLayer;
This works fine for normal views. However, myView’s layer has its borderColor and borderWidth set, and as you can see from the screenshot, the layer’s border is not getting rounded:
I also tried subclassing UIView and returning [CAShapeLayer layer] from +[Class layerClass], and setting up the view’s layer as a shape layer, but the border ended up beneath the view’s subviews.
Is it possible to round some of a view’s corners, round the view’s layer’s border, and clip the subviews underneath the layer’s border?
Note that this is not about how to round some corners and not others, but rather how to get the stroke to behave correctly.
I figured out a new way of thinking about it, thanks to David Rönnqvist’s comment.
I was trying to do the corner rounding and the stroke all in one layer. Instead, I broke it up into two layers: one to mask the view’s layer to round the corners, and the other in a view to add the stroke.
UIView *containerView = [[UIView alloc] initWithFrame:someFrame];
UIRectCorners corners = UIRectCornerBottomLeft | UIRectCornerBottomRight;
CGSize radii = CGSizeMake(kThisViewCornerRadius, kThisViewCornerRadius);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:myView.bounds
byRoundingCorners:corners
cornerRadii:radii];
// Mask the container view’s layer to round the corners.
CAShapeLayer *cornerMaskLayer = [CAShapeLayer layer];
[cornerMaskLayer setPath:path.CGPath];
containerView.layer.mask = cornerMaskLayer;
// Make a transparent, stroked layer which will dispay the stroke.
CAShapeLayer *strokeLayer = [CAShapeLayer layer];
strokeLayer.path = path.CGPath;
strokeLayer.fillColor = [UIColor clearColor].CGColor;
strokeLayer.strokeColor = [UIColor redColor].CGColor;
strokeLayer.lineWidth = 2; // the stroke splits the width evenly inside and outside,
// but the outside part will be clipped by the containerView’s mask.
// Transparent view that will contain the stroke layer
UIView *strokeView = [[UIView alloc] initWithFrame:containerView.bounds];
strokeView.userInteractionEnabled = NO; // in case your container view contains controls
[strokeView.layer addSublayer:strokeLayer];
// configure and add any subviews to the container view
// stroke view goes in last, above all the subviews
[containerView addSubview:strokeView];
Zev Eisenberg's answer is the right one.
Although I prefer:
[self.layer addSublayer:strokeLayer];
instead of creating and adding a subview:
CGSize radii = CGSizeMake(radius, radius);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds
byRoundingCorners:corners
cornerRadii:radii];
// Mask the container view’s layer to round the corners.
CAShapeLayer *cornerMaskLayer = [CAShapeLayer layer];
[cornerMaskLayer setPath:path.CGPath];
self.layer.mask = cornerMaskLayer;
// Make a transparent, stroked layer which will dispay the stroke.
CAShapeLayer *strokeLayer = [CAShapeLayer layer];
strokeLayer.path = path.CGPath;
strokeLayer.fillColor = [UIColor clearColor].CGColor;
strokeLayer.strokeColor = color.CGColor;
strokeLayer.lineWidth = 2; // the stroke splits the width evenly inside and outside,
// but the outside part will be clipped by the containerView’s mask.
[self.layer addSublayer:strokeLayer];
Here is the small code. Alloc init a view and send to this method to get corners rounded. You can optionally round any of the corners u want. Also give shadow stroke color.
-(void) setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners withColor: (UIColor*) color
{
UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(9.0, 9.0)];
CAShapeLayer* shape = [[[CAShapeLayer alloc] init] autorelease];
[shape setPath:rounded.CGPath];
shape.strokeColor = [[UIColor grayColor] CGColor];
view.backgroundColor=color;
view.layer.mask = shape;
}
Call the method like this.
[self setMaskTo:ABCView byRoundingCorners:UIRectCornerAllCorners withColor:[UIColor greenColor]];

Resources