View with UIBezierPath and shadow? - ios

I have a view in a UITableViewCell which has 3 rounded corners and a shadow. I am using UIBezierPath for rounded corners but i can't drop the shadow.
This is lines of code used:
CGRect bounds2 = cell.backgroundMessageView.bounds;
UIBezierPath *maskPath2 = [UIBezierPath bezierPathWithRoundedRect:bounds2
byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight|UIRectCornerBottomRight
cornerRadii:CGSizeMake(5, 5)];
CAShapeLayer *maskLayer2 = [CAShapeLayer layer];
maskLayer2.frame = bounds2;
maskLayer2.path = maskPath2.CGPath;
cell.backgroundMessageView.layer.mask = maskLayer2;
//drop shadow
[cell.backgroundMessageView.layer setShadowColor:[UIColor blackColor].CGColor];
[cell.backgroundMessageView.layer setShadowOpacity:1];
[cell.backgroundMessageView.layer setShadowRadius:3.0];
[cell.backgroundMessageView.layer setShadowOffset:CGSizeMake(2, 2)];
And this need to be the result:
Any ideas?
Thank you!

SOLUTION!
cell.backgroundMessageView.layer.cornerRadius=5;
CGRect bounds2 = cell.backgroundMessageView.bounds;
UIBezierPath *maskPath2 = [UIBezierPath bezierPathWithRoundedRect:bounds2
byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight|UIRectCornerBottomRight
cornerRadii:CGSizeMake(5, 5)];
CAShapeLayer *maskLayer2 = [CAShapeLayer layer];
maskLayer2.frame = bounds2;
maskLayer2.path = maskPath2.CGPath;
maskLayer2.shadowRadius = 2;
maskLayer2.shadowOpacity = 0.1;
maskLayer2.shadowColor =[UIColor blackColor].CGColor;
maskLayer2.fillColor = [UIColor colorWithRed:252/256.0 green:252/256.0 blue:252/256.0 alpha:1].CGColor;
maskLayer2.shadowOffset = CGSizeMake(0, 1);
[cell.backgroundMessageView.layer insertSublayer:maskLayer2 atIndex:0];

Related

How to append arrow head to UIBezierPath

I need help in adding arrow head to UIBezierPath.
I have created multiple lines by using UIBezierPath, which are in different directions.
Now, I want to create arrow head at the end point of the line.
I tried to add UIImage to UILable using NSAttributedString to UILable with NSTextAttachment.
But, here problem is arrow head is always down. And I want to align arrow along the line.
Here is my code:
UIBezierPath *ShotPath = [UIBezierPath bezierPath];
NSValue *PointValue = [[[PathArray objectAtIndex:i] valueForKey:#"ShotPath"] objectAtIndex:k];
CGPoint FirstPoint; = [PointValue CGPointValue];
[ShotPath moveToPoint:FirstPoint];
CAShapeLayer *line = [CAShapeLayer layer];
line.lineWidth = 4.0;
line.path=ShotPath.CGPath;
line.fillColor = [UIColor clearColor].CGColor;
line.strokeColor = [UIColor colorWithRed:231/255.0 green:83/255.0 blue:73/255.0 alpha:1].CGColor;
[[BaseView layer] addSublayer:line];
NSValue *PointValue = [[[PathArray objectAtIndex:i] valueForKey:#"ShotPath"] objectAtIndex:[[[PathArray objectAtIndex:i] valueForKey:#"ShotPath"] count]-1];
CGPoint OtherPoint = [PointValue CGPointValue];
UILabel *lbl = [[UILabel alloc]initWithFrame:CGRectMake(OtherPoint.x-6, OtherPoint.y-8, 12, 12)];
lbl.backgroundColor =[UIColor clearColor];
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = [UIImage imageNamed:#"DropDown_Icon"];
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
lbl.attributedText = attachmentString;
[lbl setTextColor:[UIColor blackColor]];
lbl.font =[UIFont boldSystemFontOfSize:22.0];
[BaseView addSubview:lbl];
Here is my current output :
By the reference of this answer:
append arrowhead to UIBezierPath
Solved my query:
Answer:
- (void)viewDidLoad {
[super viewDidLoad];
UIBezierPath *path = [UIBezierPath bezierPath];
CGPoint point1 = CGPointMake(100, 100);
CGPoint point2 = CGPointMake(300, 300);
[path moveToPoint:point1];
[path addQuadCurveToPoint:point2 controlPoint:point1];
CAShapeLayer *shape = [CAShapeLayer layer];
shape.path = path.CGPath;
shape.lineWidth = 10;
shape.strokeColor = [UIColor blueColor].CGColor;
shape.fillColor = [UIColor clearColor].CGColor;
shape.frame = self.view.bounds;
[self.view.layer addSublayer:shape];
CGFloat angle = atan2f(point2.y - point1.y, point2.x - point1.x);
CGFloat distance = 15.0;
path = [UIBezierPath bezierPath];
[path moveToPoint:point2];
[path addLineToPoint:[self calculatePointFromPoint:point2 angle:angle + M_PI_2 distance:distance]]; // to the right
[path addLineToPoint:[self calculatePointFromPoint:point2 angle:angle distance:distance]]; // straight ahead
[path addLineToPoint:[self calculatePointFromPoint:point2 angle:angle - M_PI_2 distance:distance]]; // to the left
[path closePath];
shape = [CAShapeLayer layer];
shape.path = path.CGPath;
shape.lineWidth = 2;
shape.strokeColor = [UIColor redColor].CGColor;
shape.fillColor = [UIColor redColor].CGColor;
shape.frame = self.view.bounds;
[self.view.layer addSublayer:shape];
}
- (CGPoint)calculatePointFromPoint:(CGPoint)point angle:(CGFloat)angle distance:(CGFloat)distance {
return CGPointMake(point.x + cosf(angle) * distance, point.y + sinf(angle) * distance);
}

How to set corner radius value with CAShaperLayer?

i drew a vertical line with UIBeizerPath and i need this line to have a corner radius with a value of 5. i tried to recall [pathLayer setCornerRadius: 5]; but I do not get results ... Can you help me? how can I assign a corner radius value? this is the code I use
// crea le barre del grafico e gli assegna l'altezza della label y corrispondente
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(xPaddingFromYAxis +spaceBetweenBar *j, 200)];
[path addLineToPoint:CGPointMake(xPaddingFromYAxis +spaceBetweenBar *j, yLabelValue.center.y )];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.bounds;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [UIColor darkGrayColor].CGColor;
pathLayer.fillColor = nil;
pathLayer.lineWidth = 50;
[pathLayer setCornerRadius:5];
pathLayer.masksToBounds = NO;
[scroll.layer addSublayer:pathLayer];
You need to set mask to bound as 'YES'. pathLayer.masksToBounds = YES;
Try this and see:
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(xPaddingFromYAxis +spaceBetweenBar *j, 200)];
[path addLineToPoint:CGPointMake(xPaddingFromYAxis +spaceBetweenBar *j, yLabelValue.center.y )];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.bounds;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [UIColor darkGrayColor].CGColor;
pathLayer.fillColor = nil;
pathLayer.lineWidth = 50;
[pathLayer setCornerRadius:5];
pathLayer.masksToBounds = YES;
[scroll.layer addSublayer:pathLayer];

Custom button in Objective C

I want to design a custom button in Objective C and the button is like a tick mark given bellow . Is it possible to design without using images?
Use UIBezierPath & CAShapeLayer as follow..
UIBezierPath* mybezierpath = [[UIBezierPath alloc]init];
[mybezierpath moveToPoint:CGPointMake(40.0, 55.0)];
[mybezierpath addLineToPoint:CGPointMake(130.0,160.0)];
[mybezierpath addLineToPoint:CGPointMake(200.0, 60.0)];
CAShapeLayer *lines = [CAShapeLayer layer];
lines.path = mybezierpath.CGPath;
lines.bounds = CGPathGetBoundingBox(lines.path);
lines.strokeColor = [UIColor greenColor].CGColor;
lines.fillColor = [UIColor clearColor].CGColor; /*if you just want lines*/
lines.lineWidth = 3;
lines.position = CGPointMake(self.myButton.frame.size.width/2.0, self.myButton.frame.size.height/2.0);
lines.anchorPoint = CGPointMake(.5, .5);
[self.myButton.layer addSublayer:lines];
This will Give you result like this..
Adjust points of path According to the Button you have...
Hope this helps.
Apply CAShapeLayer to your UIButton's Layer
Here is an example for you:
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 90)];
btn.backgroundColor = [UIColor purpleColor];
UIBezierPath *bPath = [UIBezierPath bezierPath];
[bPath moveToPoint:CGPointMake(25, 40)];
[bPath addLineToPoint:CGPointMake(35, 60)];
[bPath addLineToPoint:CGPointMake(75, 20)];
CAShapeLayer *sLayer = [CAShapeLayer layer];
sLayer.strokeColor = [UIColor greenColor].CGColor;
sLayer.lineWidth = 3.0f;
sLayer.path = bPath.CGPath;
sLayer.fillColor = [UIColor clearColor].CGColor;
[btn.layer addSublayer:sLayer];
[self.view addSubview:btn];
Output:
Hope this helps!

Drawing an image on a UIView, and making a transparent hole to see the UIView underneath

I have a UIView I'm trying to put together which will be layered above another view. This new view needs to have a fully transparent hole in it. I've attached a screenshot of what it is I'm trying to accomplish (checkerboard pattern is the underlying UIView that will be adding this new UIView as a sublayer, red is a UIImage).
I have the following code that will render the black background with the hole in the center:
- (void)
drawRect:(CGRect)rect
{
CGRect boxRect = CGRectMake(_location.x - (kPointRadius/2), _location.y - (kPointRadius/2), kPointRadius, kPointRadius);
UIBezierPath *path = [UIBezierPath
bezierPathWithRoundedRect:CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height)
cornerRadius:0];
UIBezierPath *circlePath = [UIBezierPath
bezierPathWithRoundedRect:boxRect
cornerRadius:kPointRadius];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.borderWidth = 5.0;
fillLayer.borderColor = [UIColor redColor].CGColor;
fillLayer.opacity = 0.7;
[self.layer addSublayer:fillLayer];
}
However, when I add an image to that and use [[UIImage imageNamed:#"testimg" drawAtPoint:CGPointMake(x, y)]; to add the image, the image covers the hole.
Can anyone point me in the right direction here? I'm stumped.
EDIT: I'm now able to get it almost there. I can get everything I need EXCEPT the image layered on top of the black, 90% opaque background is also at 90% opacity.
CGRect boxRect = CGRectMake(
_location.x - (kPointRadius/2),
_location.y - (kPointRadius/2),
kPointRadius,
kPointRadius);
UIBezierPath *path = [UIBezierPath
bezierPathWithRoundedRect:CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height) cornerRadius:0];
UIBezierPath *circlePath = [UIBezierPath
bezierPathWithRoundedRect:boxRect
cornerRadius:kPointRadius];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];
UIImage *image = [UIImage imageNamed:#"testimg"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(13, 57, 350, 230)];
imageView.image = image;
CGRect r = CGRectMake(self.layer.frame.origin.x, self.layer.frame.origin.y, self.layer.frame.size.width, self.layer.frame.size.height);
UIGraphicsBeginImageContextWithOptions(r.size, NO, 0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextAddPath(c, CGPathCreateCopy(path.CGPath));
CGContextEOClip(c);
CGContextFillRect(c, r);
UIImage* maskim = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CALayer* mask = [CALayer layer];
mask.frame = r;
mask.contents = (id)maskim.CGImage;
imageView.layer.mask = mask;
self.layer.mask = mask;
self.layer.backgroundColor = [UIColor blackColor].CGColor;
self.layer.opacity = 0.8;
[self.layer addSublayer:imageView.layer];
EDIT: I'm now able to get it almost there. I can get everything I need EXCEPT the image layered on top of the black, 90% opaque background is also at 90% opacity.
Instead of setting its opacity, you could set the layer's background color to [UIColor colorWithWhite:0.0 alpha:0.9].

Create custom rounded rectangle button corner on top-left?

I have a custom button that I want to make top-left border of it look like normal round rectangle.
I found code that makes all corners round:
_myButton.layer.cornerRadius = 8;
_myButton.layer.borderWidth = 0.5;
_myButton.layer.borderColor = [UIColor grayColor].CGColor;
_myButton.clipsToBounds = YES;
How can I fix the code to make it round just in the top-left side?
Edit:
_myButton.layer.borderWidth = 2;
_myButton.layer.borderColor = [UIColor blackColor].CGColor;
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:_myButton.bounds
byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
cornerRadii:CGSizeMake(7.0, 7.0)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = _myButton.bounds;
maskLayer.path = maskPath.CGPath;
_myButton.layer.mask = maskLayer;
[maskLayer release];
This code does not work. The whole button disappears.
You almost got it, but, after building your CAShapeLayer, use it to add itself as a sublayer of your button's layer, not as an alpha mask to hide some parts of your button (in that case the corners).
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(10,300,300,40);
[button setTitle:#"Hey" forState:(UIControlStateNormal)];
[button setTitleColor:[UIColor blueColor] forState:(UIControlStateNormal)];
UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:button.bounds
byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
cornerRadii:CGSizeMake(7.0, 7.0)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = button.bounds;
shapeLayer.path = shapePath.CGPath;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
shapeLayer.lineWidth = 2;
[button.layer addSublayer:shapeLayer];
[self.view addSubview:button];
CAShapeLayer * positiveCorner = [CAShapeLayer layer];
positiveCorner.path = [UIBezierPath bezierPathWithRoundedRect: self.button.bounds
byRoundingCorners: UIRectCornerTopRight | UIRectCornerBottomRight
cornerRadii: (CGSize){5, 5}].CGPath;
self.button.layer.mask = positiveCorner;

Resources