iOS: CAShapeLayer, Change color of outer layer - ios

I am currently using CAShapeLayer for one of my requirement. I was successful in implementing the fillcolor, strokecolor, etc... but I wanted to change the color of outer part of that CAShapeLayer. I tried doing it with backgroundcolor, & followed many answers from SO, but was unable to do it. Could anyone guide me with the solution. Screenshot attached
Edit 1: Code for creating the layer
// create layer mask for map
CAShapeLayer *maskLayer = [CAShapeLayer layer];
mapView.layer.mask = maskLayer;
// maskLayer.backgroundColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7] CGColor];
self.maskLayer = maskLayer;
// create shape layer for circle we'll draw on top of map (the boundary of the circle)
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.lineWidth = 3.0;
circleLayer.fillColor = [[UIColor clearColor] CGColor];
circleLayer.strokeColor = [[UIColor blackColor] CGColor];
// circleLayer.borderColor = [[UIColor blackColor] CGColor];
// circleLayer.backgroundColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7] CGColor];
[mapView.layer addSublayer:circleLayer];
self.circleLayer = circleLayer;
Edit 2: Xcode's Viewer's Debugger
In the above image I can see that I have set the background color to self.view. But I want it to be over my map view & the the color should be semi transparent so that map data outside circle should also be visible.

Have you tried using XCode views's debugger to know where this white background belongs in your view hierarchy ?
You're using your view's maskLayer as a circle. So my guess is that this white background must be OUTSIDE your view - everything out your mask gets clipped - so you should probably try to change your viewController's view backgroundColor (or any other view that is just above your custom rounded view)

[self.view.layer setBackgroundColor:[UIColor grayColor].CGColor];
UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:self.view.center
radius:45.0
startAngle:0
endAngle:2.0*M_PI
clockwise:YES];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.bounds = CGRectMake(0, 0, 2.0*(45.0), 2.0*(45.0));
circleLayer.path = circle.CGPath;
circleLayer.strokeColor = [UIColor orangeColor].CGColor;
circleLayer.fillColor = [UIColor whiteColor].CGColor;
circleLayer.lineWidth = 3.0; // your line width
[self.view.layer addSublayer:circleLayer];
See if it helps you.

Related

CAShapeLayer draws a circle in center as a sideeffect of line cap set to kCALineJoinRound

I'm drawing a segment of a pie chart with the following code:
CAShapeLayer *segment = [CAShapeLayer layer];
UIBezierPath *segmentPath = [UIBezierPath bezierPath];
[segmentPath addArcWithCenter:segmentCenter radius:segmentRadius startAngle:angle1 endAngle:angle2 clockwise:YES];
segment.path = [segmentPath CGPath];
[segment setLineCap:kCALineJoinRound]; // this is the line which causes this
segment.lineWidth = 8;
segment.fillColor = [[UIColor clearColor] CGColor];
segment.strokeColor = [[UIColor orangeColor] CGColor];
[self.layer addSublayer:segment];
and as a sideffect of setting kCALineJoinRound I get also a little circle inside. I need to get rid of it, can you help me?
Solved, the problem was due to the CAShapeLayer being added twice in layoutSubviews which caused this strange effect.

Add lines on ImageView IOS (objective c)

I need some help to get this thing working..
Basically on button click, I have to add a line of fixed width with circle end points on the ImageView. User can add upto 5 lines. If I click on any circle (red dot) end point of line, it should allow to resize the line. Point can be dragged to any position on screen and line has to be straight. At the end, i should be able to calculate the length of each line. I just spent a lot of time on this and referring other similar answers. But so far, no luck.. Any reference code or links is greatly appreciated.
Thanks!
WOW, where to even start. OK, first of all, you should not be doing your drawing in the "viewDidLoad" method of your ViewController. You should make a subclass of UIView (let's call it DrawView) and do all your drawing within the "drawRect" method. And within DrawView, you can then intercept touches.
So to get a little more precise:
create subclass of UIView called DrawView
Move your drawing into the drawRect method
Within DrawView, over-ride the various "touchesXXXX" methods (of UIResponder) to detect and respond to touches and figure out what shape has been touched
Within the storyboard, drag a UIView object onto your ViewController and make sure it's class is set to "DrawView".
This is for starters. Haven't even talked about how to record/store your various points and shapes.
To Draw line on image view the following code work for me even in view did load.
first int image view
second write following code
//line 1
CAShapeLayer *shapeLayerOne = [CAShapeLayer layer];
shapeLayerOne.path = [LineOne CGPath];
shapeLayerOne.strokeColor = [[UIColor blueColor] CGColor];
shapeLayerOne.lineWidth = 1.0;
shapeLayerOne.fillColor = [[UIColor clearColor] CGColor];
//line 2
CAShapeLayer *shapeLayerTwo = [CAShapeLayer layer];
shapeLayerTwo.path = [LineTwo CGPath];
shapeLayerTwo.strokeColor = [[UIColor blueColor] CGColor];
shapeLayerTwo.lineWidth = 1.0;
shapeLayerTwo.fillColor = [[UIColor clearColor] CGColor];
//line 3
CAShapeLayer *shapeLayerThree = [CAShapeLayer layer];
shapeLayerThree.path = [LineThree CGPath];
shapeLayerThree.strokeColor = [[UIColor blueColor] CGColor];
shapeLayerThree.lineWidth = 1.0;
shapeLayerThree.fillColor = [[UIColor clearColor] CGColor];
//line 4
CAShapeLayer *shapeLayerFour = [CAShapeLayer layer];
shapeLayerFour.path = [LineFour CGPath];
shapeLayerFour.strokeColor = [[UIColor blueColor] CGColor];
shapeLayerFour.lineWidth = 1.0;
shapeLayerFour.fillColor = [[UIColor clearColor] CGColor];
[self.view.layer addSublayer:shapeLayerOne];
[self.view.layer addSublayer:shapeLayerTwo];
[self.view.layer addSublayer:shapeLayerThree];
[self.view.layer addSublayer:shapeLayerFour];
your output is blue line

iOS UIButton with custom shapes

How to create 2 buttons in iOS with custom shapes. I need to draw two buttons like Diagonal of a rectangle. Left side is one button and right side is another button. I've tried using Bezier paths, But how to make them adaptive for all devices ?
Here is my code that I've tried for one button
UIBezierPath* bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 138, 118)];
[UIColor.blackColor setStroke];
bezierPath.lineWidth = 20;
[bezierPath stroke];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = self.Btn.bounds;
shapeLayer.path = bezierPath.CGPath;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
shapeLayer.lineWidth = 120;
self.Btn.layer.mask = shapeLayer;
cant u just do one button,
subclass it and hittest the CGPoint to determine which shape you should set highlighted/selected/etc

Why don't added sublayers show up in screenshot?

I'm trying to track down a bug in some iOS code for an iPad app. In one of our views, we've added sublayers to have a shadow and make sure the bottom of the view has rounded edges. Here's the code where we add the sublayers:
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds
byRoundingCorners:(UIRectCornerBottomLeft|UIRectCornerBottomRight)
cornerRadii:CGSizeMake(12.0f, 12.0f)];
// Create the shadow layer
shadowLayer = [CAShapeLayer layer];
[shadowLayer setFrame:self.bounds];
[shadowLayer setMasksToBounds:NO];
[shadowLayer setShadowPath:maskPath.CGPath];
shadowLayer.shadowColor = [UIColor blackColor].CGColor;
shadowLayer.shadowOffset = CGSizeMake(0.0f, 0.0f);
shadowLayer.shadowOpacity = 0.5f;
shadowLayer.shadowRadius = 6.0f;
roundedLayer = [CALayer layer];
[roundedLayer setFrame:self.bounds];
[roundedLayer setBackgroundColor:[UIColor colorFromHex:#"#e4ecef"].CGColor];
[self.layer insertSublayer:shadowLayer atIndex:0];
// Add inner view (since we're rounding corners, parent view can't mask to bounds b/c of shadow - need extra view)
maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
innerView = [[UIView alloc] initWithFrame:self.bounds];
innerView.backgroundColor = [UIColor whiteColor];
innerView.layer.mask = maskLayer;
[self addSubview:innerView];
It shows up fine on the screen of the iPad, but I want to take a screenshot programmatically. I've added a category to UIView with this method:
- (UIImage*)screenshot {
UIGraphicsBeginImageContext(self.frame.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
return viewImage;
}
When I look at the screenshot that is taken, it no longer has the rounded corners or the shadow behind my view. Why aren't they showing up?
Found an explanation here: CALayer renderInContext
Additionally, layers that use 3D transforms are not rendered, nor are
layers that specify backgroundFilters, filters, compositingFilter, or
a mask values.
It looks like some sublayers can't be handled by renderInContext, which is why they aren't showing up in my screenshots.
Gradient sublayers
The snapshot is not taking any gradient layers with alpha channel in it.
Remove the alpha from colors, works for me

How to remove sharp rectangle edges from UIButton control?

Take a look at the following image:
As you can see the edges are sharp rectangle and they are coming out of the rounded corner button. How can I not show the edges and only show the round button?
UPDATE (Solution):
I used the following code to achieve the round corners:
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.stopButton.bounds
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(12.0, 12.0)];
// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.stopButton.bounds;
maskLayer.path = maskPath.CGPath;
// Set the newly created shape layer as the mask for the image view's layer
self.stopButton.layer.mask = maskLayer;
NEW PROBLEM:
This code gives me the error on the startButtonRound.layer.cornerRadius line.
UIButton *roundStartButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
roundStartButton.frame = CGRectMake(10, 10, 100, 20);
[roundStartButton setBackgroundImage:[UIImage imageNamed:#"green_gradient.jpg"] forState:UIControlStateNormal];
roundStartButton.layer.cornerRadius = 12.0;
UIBarButtonItem *startButton = [[UIBarButtonItem alloc] initWithCustomView:roundStartButton];
You could do this with CALayer alone:
CALayer *myLayer = [CALayer layer];
[myLayer setMasksToBounds:YES];
[myLayer setCornerRadius:5.0f];
[myLayer setBorderWidth:1.0f];
[myLayer setBorderColor: [[UIColor blackColor] CGColor]];
[myLayer setBackgroundColor: [[UIColor whiteColor] CGColor]];
You'll also want to include the QuartzCore framework and include the frameworks header in your own.
#include <QuartzCore/QuartzCore.h>
Hope this helps
Tim
I think all that can be accomplished with:
self.stopButton.layer.cornerRadius = 12.0;
But did you try
self.stopButton.opaque = NO;
self.stopButton.backgroundColor = [UIColor clearColor];
?
form the look of the image you have set your UIButton bckground color to 'White'. Make it 'Clear Color'.

Resources