Draw Line and get actions between sections - ios

I want to draw lines which is shown in the image.
and I have to add four labels with name Section 1,Section 2,Section 3,Section 4.
I have tried below code to draw lines and it works
-(UIBezierPath*)createBezierPathWithMoveToPoint:(CGPoint)moveToPoint andlineToPoint:(CGPoint)toPoint
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:moveToPoint];
[path addLineToPoint:toPoint];
return path;
}
-(CAShapeLayer*)createLayerWithPath:(CGPathRef)path strokColor:(UIColor *)colorStroke lineWidth:(CGFloat)width fillColor:(UIColor *)colorFill
{
CAShapeLayer *layer = [CAShapeLayer layer];
layer.path = path;
layer.strokeColor = [colorStroke CGColor];
layer.lineWidth = width;
layer.fillColor = [colorFill CGColor];
return layer;
}
By using above code I have achieved lines and I have added for UIlabel's manually. Can anyone please help me to get action like UIButton actions, when user touch in between these sections. ?
OR
If there is any best and easiest way to achieve this please let me know.

Related

Can't remove CAShapeLayer from Super Layer

I'm trying to remove my circle that I've created as a CAShapeLayer and drawn with UIBezier path if I can't receive a measurement. In my (void)drawRect method for my UIView class, I create and draw a circle if a measurement is found. However, if there is no measurement I'd like to get rid of the circle. For some reason I can't.
Here is the code that creates the circle in -(void)drawRect
- (void)drawRect:(CGRect)rect {
CAShapeLayer *grayCircle = [CAShapeLayer layer];
CAShapeLayer *progressArc = [CAShapeLayer layer];
DBHelper *dbHelper = [DBHelper getSharedInstance];
if ([dbHelper getPairedDevice]==nil) {
[grayCircle removeFromSuperlayer]; // I want to remove the grayCirle if no measurement is found AKA getPairedDevice = nil
}
....
if (_latestMeasurement) {
...
// Gray outer circle
UIBezierPath *grayCirclePath=[UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
grayCircle.path = [grayCirclePath CGPath];
grayCircle.position = CGPointMake(realBounds.origin.x, realBounds.origin.y);
grayCircle.fillColor = [UIColor clearColor].CGColor;
grayCircle.lineCap=kCALineCapRound;
grayCircle.strokeColor = [UIColor grayColor].CGColor;
grayCircle.lineWidth = 30;
// Progress arc
UIBezierPath *progressPath=[UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:startAngle endAngle:patientOutput clockwise:YES];
progressArc.path = [progressPath CGPath];
progressArc.position = CGPointMake(grayCircle.frame.origin.x, grayCircle.frame.origin.y);
progressArc.fillColor = [UIColor clearColor].CGColor;
progressArc.lineCap=kCALineCapRound;
progressArc.lineWidth = 30;
[self.layer addSublayer:grayCircle];
[self.layer addSublayer:progressArc];
}
So here's the issue: The following lines of code aren't removing the gray circle:
if ([dbHelper getPairedDevice]==nil) {
[grayCircle removeFromSuperlayer];
}
I'm wondering why is that the case, and how can I remove it from the view's sublayer?
You are creating a new reference to grayCircle each time you go through drawRect. When you remove it - you're removing the new one, not the one you drew previously.
If you already have it, you need to find it first, then remove it - going through the subViews, or maintain a reference to it at the class level

Implement drawing gradient arc with CAShapeLayer

Referring to the accepted answer found here I'm trying to implement this and running into an issue with the path of the CAShapeLayerThe code I have is as follows:
-(void)drawGradientArc{
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
CAShapeLayer *circleLayer = [CAShapeLayer new];
circleLayer.lineWidth = 25;
circleLayer.fillColor = [UIColor clearColor].CGColor;
circleLayer.strokeColor = [UIColor redColor].CGColor;
CGFloat radius = 150;
[bezierPath addArcWithCenter:self.view.center radius:radius startAngle:0 endAngle:M_PI clockwise:YES];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0,0);
gradientLayer.endPoint = CGPointMake(1,0);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:circleLayer];
circleLayer.path = bezierPath.CGPath;
[self.view.layer addSublayer:circleLayer];
}
This will draw the half circle arc correctly but the path for the gradients is not being set correctly and I was unable to piece together how exactly to configure the code to get this to work using a gradient. There is a CGPathCreateCopyByStrokingPath that I think I may also need to call to set the path properly for the gradient but was not quite sure how. Any help on how to structure the code to get this working would be appreciated. I've also included an image of the gradient that I'm trying to reproduce. a CAShapeLayer and CAGradientLayerapproach would be ideal.
Problem 1: Your layers have no frames. Add this:
gradientLayer.frame = self.view.layer.bounds;
circleLayer.frame = gradientLayer.bounds;
Problem 2: You are adding the wrong layer to your view's layer. Where you have:
[self.view.layer addSublayer:circleLayer];
say this instead:
[self.view.layer addSublayer:gradientLayer];
Result:

Not able to round caps in UIBezierPath Arc even with kCGLineCapRound

I am not able to display rounded caps on my Arc created using UIBezierPath. It's still perfectly squared regardless I set kCGLineCapRound or not.
This topic should be same as this one, however solution is not working.
Here is the example code I have in viewWillAppear (for test purposes only):
int radius = 100;
CAShapeLayer *arc = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 50) radius:radius startAngle:M_PI endAngle:M_PI/150 clockwise:YES];
path.lineCapStyle = kCGLineCapRound;
arc.path = path.CGPath;
arc.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius, CGRectGetMidY(self.view.frame)-radius);
arc.fillColor = [UIColor clearColor].CGColor;
arc.strokeColor = [UIColor purpleColor].CGColor;
arc.lineWidth = 10.0f;
arc.cornerRadius = 3.0f;
Here is how it looks:
I am helpless so I would appreciate any help. Thanks guys.
Use the lineCap property of the CAShapeLayer rather than the lineCapStyle of the path.
arc.lineCap = kCALineCapRound;
If you are calling the path's stroke method (e.g. if you're doing this in drawRect or manually drawing in a UIGraphicsContext) then set attributes like the cap or join styles in the UIBezierPath. But when using CAShapeLayer, the attributes are set on the shape layer, not the path.

How can i remove the circle drawn in iOS?

I have this code where I draw circles on the screen, and I want to remove just the last circle drawn. What can I do? The code is set to draw a circle when I tap twice. I want to remove the last circle drawn when I tap one time.
- (UIBezierPath *)makeCircleAtLocation:(CGPoint)location radius:(CGFloat)radius {
iOSCircle *circle = [[iOSCircle alloc] init];
circle.circleCenter = location;
circle.circleRadius = radius;
[totalCircles addObject:circle];
UIBezierPath *path = [UIBezierPath bezierPath];
[path addArcWithCenter:circle.circleCenter
radius:circle.circleRadius
startAngle:0.0
endAngle:M_PI * 2.0
clockwise:YES];
return path;
}
- (IBAction) tapEvent: (UIGestureRecognizer *) sender
{
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [[self makeCircleAtLocation:location radius:2.5] CGPath];
shapeLayer.strokeColor = [[UIColor redColor] CGColor];
//shapeLayer.fillColor = nil;
shapeLayer.lineWidth = 2.5;
// Add CAShapeLayer to our view
[self.view.layer addSublayer:shapeLayer];
// Save this shape layer in a class property for future reference,
// namely so we can remove it later if we tap elsewhere on the screen.
self.circleLayer = shapeLayer;
}
}
Create your circle in a distinct CAShapeLayer layer using a CGPath, and add it as a sublayer of your view.layer. That way, you will have total control over that circle (showing or hiding it).

Drawing a line with Bezierpath using CAShapeLayer object

I am making an image editor which can create different shapes objects like circle, triangle and square which can also be updated or removed. So I have used CAShapeLayer for creating shapes objects.
Now I also want to draw a line on image which can also be updated or removed so I have used bezierpath and CAShapeLayer to create the line, it is working fine. BUT now the problem is that when I want to select any existing line it can be selected any where close to line tool because CAShapeLayer also set the fill region which will be a straight line from start point to end point.
My question is that how can I create line with no fill region using CAShapeLayer.
Here is my code for creating line:
CAShapeLayer *line = [CAShapeLayer layer];
// Using bezierpath to make line
UIBezierPath *linePath=[UIBezierPath bezierPath];
// Creating L with line
[linePath moveToPoint:point1];
[linePath addToPoint:point2];
[linePath addToPoint:point3];
line.path=linePath.CGPath;
// Configure the appearence of the line
line.fillColor = Nil;
line.opacity = 1.0;
line.strokeColor = [UIColor whiteColor].CGColor;
Any idea on this will be really appreciated.
Can you try this. Its work for me
CAShapeLayer *line = [CAShapeLayer layer];
UIBezierPath *linePath=[UIBezierPath bezierPath];
[linePath moveToPoint:CGPointMake(startx, starty)];
[linePath addLineToPoint:CGPointMake(endx, endy)];
line.lineWidth = 10.0;
line.path=linePath.CGPath;
line.fillColor = shapecolor.CGColor;
line.strokeColor = shapecolor.CGColor;
[[self.view layer] addSublayer:line];
I understand you I experienced this issue as well try this:
GPathRef linePathRef = linePath.CGPath
linePathRef = CGPathCreateCopyByStrokingPath(linePathRef, NULL, line.lineWidth, kCGLineCapRound, kCGLineJoinRound, 1);
BOOL pathContainsPoint = CGPathContainsPoint(linePathRef, NULL, touchLocation, NO);
if(pathContainsPoint){
//Do something with the cashapelayer line...
}else{
//Do something here if needed...
}

Resources