iOS adding points to quadratic curves and manipulating - ios

I'm starting out with a straight line, as shown below.
I need the user to be able to drag and manipulate this line with their finger in real time. So they might end up with a series or curves as below:
It is simple to do this with one curve, as in the code below.
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
controlPoint = [[touches anyObject] locationInView:self];
CGRect controlRect = CGRectMake(controlPoint.x - 50.0, controlPoint.y - 50.0, 100.0, 100.0);
[self setNeedsDisplayInRect:controlRect];
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, 0 , screenHeight/2 + gapDistance);
CGContextAddQuadCurveToPoint(context, controlPoint.x + gapDistance, controlPoint.y + gapDistance, 100, screenHeight/2 + gapDistance);
CGContextStrokePath(context);
}
My question is, how do I do it with multiple curves? I will also need to be able to add smaller curves to existing curves if the user so desires.

Related

move Arc drawn using CGContextAddArc iOS Objective c

I have drawn an arc using below code,
CGPoint circleCenter = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 20.0);
CGContextSetStrokeColorWithColor(context,[UIColor redColor].CGColor);
CGContextAddArc(context, circleCenter.x , circleCenter.y, 100, [self radians:315], [self radians:135], 1);
CGContextStrokePath(context);
now i need to know can i move this arc in circular path using below method.?
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
If not how can i program an arc shape which can be moved using above method.?

iOS drawing imitate flat tip pen

I'm creating a drawing app and I want to simulate a flat tip pen. Surprisingly it turned to pretty difficult task. This is my solution:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.drawingImageView];
currentPoint = CGPointMake(roundf(currentPoint.x), roundf(currentPoint.y));
UIGraphicsBeginImageContext(self.drawingImageView.frame.size);
[self.drawingImageView.image drawInRect:CGRectMake(0, 0, self.drawingImageView.frame.size.width, self.drawingImageView.frame.size.height)];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextMoveToPoint (ctx, lastPoint.x + 8.f, lastPoint.y - 8.f);
CGContextAddLineToPoint(ctx, currentPoint.x + 8.f, currentPoint.y - 8.f);
CGContextAddLineToPoint(ctx, currentPoint.x - 8.f, currentPoint.y + 8.f);
CGContextAddLineToPoint(ctx, lastPoint.x - 8.f, lastPoint.y + 8.f);
CGContextAddLineToPoint(ctx, lastPoint.x + 8.f, lastPoint.y - 8.f);
CGContextClosePath(ctx);
CGContextSetRGBFillColor(ctx, 0, 0, 0, 1);
CGContextDrawPath(ctx, kCGPathFillStroke);
[self.drawingImageView performSelectorInBackground:#selector(setImage:) withObject:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
}
This is how it looks:
As you can see, the edges are not smooth. I'd like to use UIBezierPath instead but I didn't find a way to achieve flat tip pen effect using UIBezierPath. Maybe there are some ways to improve my code or any other approaches (maybe UIBezierPath)?
The only app with such drawing style that I could find is the app called "Khattat". It's on arabic, you should tap second button on the main screen to open painting. It's a perfect example of what I want.
This is a pretty common problem.
The problem is with the line
UIGraphicsBeginImageContext(self.drawingImageView.frame.size);
What this does is create a new transparent image context with a size of your image view, but a scale of 1.0. Because of this scale - any drawing done in it will have to be upsampled to be displayed on a 2x or 3x display - hence your drawing coming out blurry.
The fix is amazingly simple. You can just use
UIGraphicsBeginImageContextWithOptions(drawingImageView.frame.size, NO, 0.0);
By passing 0.0 into the scale argument, Core Graphics will automatically detect the scale of the screen, and set the context's scale to match. Therefore any drawing you do in it will be done at the correct resolution.
Also, I just noticed the line
[self.drawingImageView performSelectorInBackground:#selector(setImage:) withObject:UIGraphicsGetImageFromCurrentImageContext()];
This doesn't sound like a great idea. If you look at the UIView documentation, you'll see Apple says:
Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application.
Therefore you should be doing
self.drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext()
instead.
In regards to your comments about using a UIBezierPath - I don't see any obvious advantages that this change will bring you - drawing the path into the context yourself is just as direct as using the UIBezierPath methods for drawing.
However if you still want to, you can of course use a UIBezierPath instead - you'll want to do something like the following:
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self];
currentPoint = CGPointMake(roundf(currentPoint.x), roundf(currentPoint.y));
UIGraphicsBeginImageContextWithOptions(drawingImageView.frame.size, NO, 0.0);
[drawingImageView.image drawInRect:CGRectMake(0, 0, drawingImageView.frame.size.width, drawingImageView.frame.size.height)];
UIBezierPath* path = [UIBezierPath bezierPath];
[path moveToPoint:(CGPoint){lastPoint.x + 8.f, lastPoint.y - 8.f}];
[path addLineToPoint:(CGPoint){currentPoint.x + 8.f, currentPoint.y - 8.f}];
[path addLineToPoint:(CGPoint){currentPoint.x - 8.f, currentPoint.y + 8.f}];
[path addLineToPoint:(CGPoint){lastPoint.x - 8.f, lastPoint.y + 8.f}];
[path addLineToPoint:(CGPoint){lastPoint.x + 8.f, lastPoint.y - 8.f}];
[[UIColor blackColor] set];
[path fill];
drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;

Draw Triangles inside Circle Objective-C [duplicate]

For an iPhone application I want to draw a circle, that is only for an x percentage filled.
Something like this:
I have no problems calculating the radius, the degrees or the radians, that is no problem. Also drawing the circle is already done. But how do I get the iPhone SDK to draw the part that is filled.
I can draw a rectangle that size, but not part of a circle.
I just want to draw that on a a normal context.
Hope someone can give me any pointers here.
A lot of people have showed you how this can be done in Core Graphics but it can also be done with Core Animation which gives the big addition of easily being able to animate the percentage of the pie shape.
The following code will create both the ring and the partly filled layers (even though you said that you already can draw the ring) since its nice to have both the ring and the pie shape to be drawn using the same method.
If you animate the strokeStart or strokeEnd properties of the pieShape layer you will have the percentage animate. As with all Core Animation code you will need to add QuartzCore.framework to your project and include <QuartzCore/QuartzCore.h> in your code.
// Create a white ring that fills the entire frame and is 2 points wide.
// Its frame is inset 1 point to fit for the 2 point stroke width
CGFloat radius = MIN(self.frame.size.width,self.frame.size.height)/2;
CGFloat inset = 1;
CAShapeLayer *ring = [CAShapeLayer layer];
ring.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
cornerRadius:radius-inset].CGPath;
ring.fillColor = [UIColor clearColor].CGColor;
ring.strokeColor = [UIColor whiteColor].CGColor;
ring.lineWidth = 2;
// Create a white pie-chart-like shape inside the white ring (above).
// The outside of the shape should be inside the ring, therefore the
// frame needs to be inset radius/2 (for its outside to be on
// the outside of the ring) + 2 (to be 2 points in).
CAShapeLayer *pieShape = [CAShapeLayer layer];
inset = radius/2 + 2; // The inset is updated here
pieShape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
cornerRadius:radius-inset].CGPath;
pieShape.fillColor = [UIColor clearColor].CGColor;
pieShape.strokeColor = [UIColor whiteColor].CGColor;
pieShape.lineWidth = (radius-inset)*2;
// Add sublayers
// NOTE: the following code is used in a UIView subclass (thus self is a view)
// If you instead chose to use this code in a view controller you should instead
// use self.view.layer to access the view of your view controller.
[self.layer addSublayer:ring];
[self.layer addSublayer:pieShape];
Use CGContext's arc functions:
CGContextAddArc(context,
centerX,
centerY,
radius,
startAngleRadians,
endAngleRadians,
clockwise ? 1 : 0);
See the documentation for CGContextAddArc().
Try this:
CGContextMoveToPoint(the center point)
CGContextAddLineToPoint(the starting point of the fill path on the circumference)
CGContextAddArcToPoint(the ending point of the fill path on the circumference)
CGContextAddLineToPoint(the center point)
CGContextFillPath
I implemented a pie progress view that looks similar to what you are doing. It's open source. Hopefully the source code will help.
SSPieProgressView.h source
SSPieProgressView.m source
CircleViewController.h
#import <UIKit/UIKit.h>
#interface CircleViewController : UIViewController
#end
CircleViewController.m
#import "CircleViewController.h"
#import "GraphView.h"
#interface CircleViewController ()
#end
#implementation CircleViewController
- (void)viewDidLoad {
[super viewDidLoad];
GraphView *graphView = [[GraphView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
graphView.backgroundColor = [UIColor whiteColor];
graphView.layer.borderColor = [UIColor redColor].CGColor;
graphView.layer.borderWidth = 1.0f;
[self.view addSubview:graphView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
GraphView.h
#import <UIKit/UIKit.h>
#interface GraphView : UIView
#end
GraphView.m
#import "GraphView.h"
#implementation GraphView
- (void)drawRect:(CGRect)rect {
CGPoint circleCenter = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
[self drawCircleWithCircleCenter:(CGPoint) circleCenter radius:80 firstColor:[UIColor blueColor].CGColor secondeColor:[UIColor redColor].CGColor lineWidth:2 startDegree:0 currentDegree:90];
//[self drawCircleWithCircleCenter2:(CGPoint) circleCenter radius:80 firstColor:[UIColor blueColor].CGColor secondeColor:[UIColor redColor].CGColor lineWidth:2 startDegree:0 currentDegree:90];
}
- (void)drawCircleWithCircleCenter:(CGPoint) circleCenter
radius:(CGFloat)radius
firstColor:(CGColorRef)firstColor
secondeColor:(CGColorRef)secondeColor
lineWidth:(CGFloat)lineWidth
startDegree:(float)startDegree
currentDegree:(float)endDegree {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, lineWidth);
CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);
CGContextAddArc(context, circleCenter.x , circleCenter.y, radius, [self radians:startDegree], [self radians:endDegree], 0);
CGContextSetFillColorWithColor(context, firstColor);
CGContextFillPath(context);
CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);
CGContextAddArc(context, circleCenter.x, circleCenter.y, radius, [self radians:endDegree], [self radians:startDegree], 0);
CGContextSetFillColorWithColor(context, secondeColor);
CGContextFillPath(context);
}
- (void)drawCircleWithCircleCenter2:(CGPoint) circleCenter
radius:(CGFloat)radius
firstColor:(CGColorRef)firstColor
secondeColor:(CGColorRef)secondeColor
lineWidth:(CGFloat)lineWidth
startDegree:(float)startDegree
currentDegree:(float)endDegree {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, lineWidth);
CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);
CGContextAddArc(context, circleCenter.x , circleCenter.y, radius, [self radians:startDegree], [self radians:endDegree], 0);
CGContextSetFillColorWithColor(context, firstColor);
CGContextFillPath(context);
CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);
CGContextAddArc(context, circleCenter.x, circleCenter.y, radius, [self radians:endDegree], [self radians:startDegree], 0);
CGContextSetStrokeColorWithColor(context, secondeColor);
CGContextStrokePath(context);
}
-(float) radians:(double) degrees {
return degrees * M_PI / 180;
}
#end
note: you can use one of the 2 methods:
"drawCircleWithCircleCenter" or "drawCircleWithCircleCenter2"
this code if you want to split cell on 2 parts only
if you want to split cell on more than 2 parts you can check this : "Drawing a circle ,filled different parts with different color" and check the answer start with this Phrase "we have 6 class"
Well, since nobody used NSBezierPath so far, I figured I could provide the solution I recently used for the same problem:
-(void)drawRect:(NSRect)dirtyRect
{
double start = -10.0; //degrees
double end = 190.0; //degrees
NSPoint center = NSMakePoint(350, 200);
double radius = 50;
NSBezierPath *sector = [NSBezierPath bezierPath];
[sector moveToPoint:center];
[sector appendBezierPathWithArcWithCenter:center radius:radius startAngle:start endAngle:end];
[sector lineToPoint:center];
[sector fill];
}
Below is a full method I am using that does this with Core Graphics, adapting and expanding on mharper's comment above.
This code is for OSX Cocoa, but could easily be changed to iOS, by modifying how you get the context.
- (void)drawPieShapedCircleWithRadius:(CGFloat)radius
strokeColor:(CGColorRef)strokeColor
fillColor:(CGColorRef)fillColor
lineWidth:(CGFloat)lineWidth
currentDegrees:(float)currentDegrees
startDegrees:(float)startDegrees {
// get the context
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
// Set the color of the circle stroke and fill
CGContextSetStrokeColorWithColor(context, strokeColor);
CGContextSetFillColorWithColor(context, fillColor);
// Set the line width of the circle
CGContextSetLineWidth(context, 1);
// Calculate the middle of the circle
CGPoint circleCenter = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
// Move the bezier to the center of the circle
CGContextMoveToPoint(context, circleCenter.x, circleCenter.y); // move to the center point
// Draw the arc from the start point (hardcoded as the bottom of the circle) to the center
CGContextAddLineToPoint(context, circleCenter.x, circleCenter.y + radius);
// Draw the arc around the circle from the start degrees point to the current degrees point
CGContextAddArc(context, circleCenter.x , circleCenter.y, radius, [self radians:startDegrees], [self radians:startDegrees + currentDegrees], 0);
// Draw the line back into the center of the circle
CGContextAddLineToPoint(context, circleCenter.x, circleCenter.y);
// Fill the circle
CGContextFillPath(context);
// Draw the line around the circle
CGContextStrokePath(context);
}
Try this code in a UIView, Example "MyChartClass"...
- (void)drawRect:(CGRect)rect {
int c=(int)[itemArray count];
CGFloat angleArray[c];
CGFloat offset;
int sum=0;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, false);
CGContextSetShouldAntialias(context, false);
for(int i=0;i<[itemArray count];i++) {
sum+=[[itemArray objectAtIndex:i] intValue];
}
for(int i=0;i<[itemArray count];i++) {
angleArray[i]=(float)(([[itemArray objectAtIndex:i] intValue])/(float)sum)*(2*3.14);
CGContextMoveToPoint(context, radius, radius);
if(i==0)
CGContextAddArc(context, radius, radius, radius, 0,angleArray[i], 0);
else
CGContextAddArc(context, radius, radius, radius,offset,offset+angleArray[i], 0);
offset+=angleArray[i];
CGContextSetFillColorWithColor(context, ((UIColor *)[myColorArray objectAtIndex:i]).CGColor);
CGContextClosePath(context);
CGContextFillPath(context);
}
}
Implementation in your UIViewController
MyChartClass *myChartClass=[[MyChartClass alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
myChartClass.backgroundColor = [UIColor clearColor];
myChartClass.itemArray=[[NSArray alloc]initWithObjects:#"75",#"25", nil];
myChartClass.myColorArray=[[NSArray alloc]initWithObjects:[UIColor blackColor],[UIColor whiteColor], nil];
myChartClass.radius=100;
[self.view addSubview:myChartClass];
Regards.

Objective C - Sketch Application will not draw long lines

I have an iPhone app where I provide a sketch pad for the user to save a signature. An UIImageView gets added to the main view and that holds the strokes. For some reason you can only draw short lines on the pad like the following image.
I have another application for the iPad that uses the same code and it works fine. I'm not sure what could be causing it. I'm not using any touch or gesture code that would interfere with it. The following is some of the code I use.
UPDATE: If I create a UIViewController with the same class and make it the root view controller then it works fine. Something in my navigation hierarchy is doing something weird.
-(void)SetUpSignaturePad{
//create a frame for our signature capture
imageFrame = CGRectMake(self.view.frame.origin.x,
self.view.frame.origin.y,
self.view.frame.size.width + 23,
self.view.frame.size.height + 7 );
//allocate an image view and add to the main view
mySignatureImage = [[UIImageView alloc] initWithImage:nil];
mySignatureImage.frame = imageFrame;
mySignatureImage.backgroundColor = [UIColor whiteColor];
[self.view addSubview:mySignatureImage];
}
//when one or more fingers touch down in a view or window
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//did our finger moved yet?
fingerMoved = NO;
UITouch *touch = [touches anyObject];
//we need 3 points of contact to make our signature smooth using quadratic bezier curve
currentPoint = [touch locationInView:mySignatureImage];
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
lastContactPoint2 = [touch previousLocationInView:mySignatureImage];
//when one or more fingers associated with an event move within a view or window
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
//well its obvious that our finger moved on the screen
fingerMoved = YES;
UITouch *touch = [touches anyObject];
//save previous contact locations
lastContactPoint2 = lastContactPoint1;
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
//save current location
currentPoint = [touch locationInView:mySignatureImage];
//find mid points to be used for quadratic bezier curve
CGPoint midPoint1 = [self midPoint:lastContactPoint1 withPoint:lastContactPoint2];
CGPoint midPoint2 = [self midPoint:currentPoint withPoint:lastContactPoint1];
//create a bitmap-based graphics context and makes it the current context
UIGraphicsBeginImageContext(imageFrame.size);
//draw the entire image in the specified rectangle frame
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
//set line cap, width, stroke color and begin path
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
//begin a new new subpath at this point
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), midPoint1.x, midPoint1.y);
//create quadratic BĂ©zier curve from the current point using a control point and an end point
CGContextAddQuadCurveToPoint(UIGraphicsGetCurrentContext(),
lastContactPoint1.x, lastContactPoint1.y, midPoint2.x, midPoint2.y);
//set the miter limit for the joins of connected lines in a graphics context
CGContextSetMiterLimit(UIGraphicsGetCurrentContext(), 2.0);
//paint a line along the current path
CGContextStrokePath(UIGraphicsGetCurrentContext());
//set the image based on the contents of the current bitmap-based graphics context
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
//remove the current bitmap-based graphics context from the top of the stack
UIGraphicsEndImageContext();
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
//if the finger never moved draw a point
if(!fingerMoved) {
UIGraphicsBeginImageContext(imageFrame.size);
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
//calculate midpoint between two points
- (CGPoint) midPoint:(CGPoint )p0 withPoint: (CGPoint) p1 {
return (CGPoint) {
(p0.x + p1.x) / 2.0,
(p0.y + p1.y) / 2.0
};
}
I'm sorry to tell you that I haven't a real solution, but your problem most probably is due to performance issues. Why? Because you are creating an image each time a gesture is detected. Creating images requires of screen renderings that takes time and resources.
You should base your code on same project that has drawing functionalities, usually that use a view that updates their draw in the drawRect method, for you maybe a CAShapeLaywr is also fine.
Run Time Profiler in instruments and search wich method is tanking time.

Draw a 5 pixel line on UIView [duplicate]

This question already has answers here:
What's the best approach to draw lines between views?
(2 answers)
Closed 9 years ago.
I have a very simple (well hopefully very simple) question. In Objective-C, how do you draw a line between two points and add it to a UIView? I have tried using a UIImageView and manipulating its Transform property, but that ends up turning the line into a square or a rectangle when using the following code:
[[self tline] setFrame:CGRectMake(start.x, start.y, width, 5)];
[[self tline] setTransform:CGAffineTransformMakeRotation(angle)];
I have two CGPoints, start and end, and I would like to draw a dynamic 5px line between the two points and add it to my subview.
BK:
The point start is the point where the user begins touching the screen, and the point end is the point where the user's finger is currently. Obviously this will move a lot during gameplay. I need to be able to move this line to connect these two points.
I am using the touchesBegan:, Moved:, and Ended: methods to create, move, and destroy the line.
CoreGraphics
I have the following code; how do I add this line to self.view?
CGContextRef c = UIGraphicsGetCurrentContext();
CGFloat color[4] = {1.0f, 1.0f, 1.0f, 0.6f};
CGContextSetStrokeColor(c, color);
CGContextBeginPath(c);
CGContextMoveToPoint(c, start.x, start.y);
CGContextAddLineToPoint(c, end.x, end.y);
CGContextSetLineWidth(c, 5);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextStrokePath(c);
Custom UIView:
#import <UIKit/UIKit.h>
#interface DrawingView : UIView
#property (nonatomic) CGPoint start;
#property (nonatomic) CGPoint end;
- (void)drawRect:(CGRect)rect;
#end
#import "DrawingView.h"
#implementation DrawingView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); //change color here
CGFloat lineWidth = 5.0; //change line width here
CGContextSetLineWidth(context, lineWidth);
CGPoint startPoint = [self start];
CGPoint endPoint = [self end];
CGContextMoveToPoint(context, startPoint.x + lineWidth/2, startPoint.y + lineWidth/2);
CGContextAddLineToPoint(context, endPoint.x + lineWidth/2, endPoint.y + lineWidth/2);
CGContextStrokePath(context);
CGContextRestoreGState(context);
NSLog(#"%f",_end.x);
}
- (void)setEnd:(CGPoint)end
{
_end = end;
[self setNeedsDisplay];
}
#end
drawRect: is only called when I initialize the view...
Draw method in UIViewController:
- (void)drawTLine:(CGPoint)start withEndPoint:(CGPoint)end
{
[[self dview] setStart:start];
[[self dview] setEnd:end];
[[self dview] drawRect:[self dview].frame];
}
This is how I add the drawing view:
DrawingView* dview = [[DrawingView alloc] initWithFrame:self.view.frame];
[dview setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:dview];
Subclass UIView and perform custom drawing using the drawRect: method
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor); //change color here
CGFloat lineWidth = 1.0; //change line width here
CGContextSetLineWidth(context, lineWidth);
CGPoint startPoint = rect.origin; //change start point here
CGPoint endPoint = {.x = CGRectGetMaxX(rect), .y = startPoint.y} //change end point here
CGContextMoveToPoint(context, startPoint.x + lineWidth/2, startPoint.y + lineWidth/2);
CGContextAddLineToPoint(context, endPoint.x + lineWidth/2, endPoint.y + lineWidth/2);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
This will draw a black 1px line at the top of your UIView.
If you need to update the line you can just use some properties like
#property (nonatomic) CGPoint startPoint;
and provide a custom implementation for the setter like
- (void)setStartPoint:(CGPoint)point {
_point = point;
[self setNeedsDisplay]; // this will cause drawRect: to be called again
}
Do that for every property that you wish to control and make your drawRect: use such properties for drawing.
you can create and UIBezierPath like this
UIBezierPath path = [[UIBezierPath alloc] init]
[path moveToPoint: CGPoint(x,y)] // X and Y, start point
[path addLineToPoint:CGPoint(x2,y2) // X2 and Y2, end point
if you want to create a shape you can put more points with addLineToPoint: method and finish use
closePath method
I hope help you

Resources