How do you draw a line programmatically from a view controller?

I have a UIViewController . How to draw a line in one of the programmatically created views?

+80
ios objective-c uikit uiview
May 30 '13 at 21:46
source share
7 answers

There are two common methods.

  1. Using CAShapeLayer :

    • Create a UIBezierPath (replace the coordinates with whatever you want):

       UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(10.0, 10.0)]; [path addLineToPoint:CGPointMake(100.0, 100.0)]; 
    • Create a CAShapeLayer that uses this UIBezierPath :

       CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [path CGPath]; shapeLayer.strokeColor = [[UIColor blueColor] CGColor]; shapeLayer.lineWidth = 3.0; shapeLayer.fillColor = [[UIColor clearColor] CGColor]; 
    • Add this CAShapeLayer to your view layer:

       [self.view.layer addSublayer:shapeLayer]; 

    In previous versions of Xcode, you had to manually add QuartzCore.framework to the project "Link <QuartzCore/QuartzCore.h> to libraries" and import <QuartzCore/QuartzCore.h> into the .m file, but this is no longer required (if you have Included assembly settings "Enable modules" and "Automatically link frameworks").

  2. Another approach is to UIView subclass of UIView and then use CoreGraphics calls in the drawRect method:

    • Subclass UIView and define a drawRect that draws your line.

      You can do this with Core Graphics:

       - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]); CGContextSetLineWidth(context, 3.0); CGContextMoveToPoint(context, 10.0, 10.0); CGContextAddLineToPoint(context, 100.0, 100.0); CGContextDrawPath(context, kCGPathStroke); } 

      Or using UIKit :

       - (void)drawRect:(CGRect)rect { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(10.0, 10.0)]; [path addLineToPoint:CGPointMake(100.0, 100.0)]; path.lineWidth = 3; [[UIColor blueColor] setStroke]; [path stroke]; } 
    • You can then either use this view class as the base class for your NIB / storyboard or view, or you can force your view controller to programmatically add it as a subview:

       PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds]; pathView.backgroundColor = [UIColor clearColor]; [self.view addSubview: pathView]; 



The swift executions of the two approaches above are as follows:

  1. CAShapeLayer :

     // create path let path = UIBezierPath() path.move(to: CGPoint(x: 10, y: 10)) path.addLine(to: CGPoint(x: 100, y: 100)) // Create a 'CAShapeLayer' that uses that 'UIBezierPath': let shapeLayer = CAShapeLayer() shapeLayer.path = path.cgPath shapeLayer.strokeColor = UIColor.blue.cgColor shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineWidth = 3 // Add that 'CAShapeLayer' to your view layer: view.layer.addSublayer(shapeLayer) 
  2. UIView subclass:

     class PathView: UIView { var path: UIBezierPath? { didSet { setNeedsDisplay() } } var pathColor: UIColor = .blue { didSet { setNeedsDisplay() } } override func draw(_ rect: CGRect) { // stroke the path pathColor.setStroke() path?.stroke() } } 

    And add it to your view hierarchy:

     let pathView = PathView() pathView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(pathView) NSLayoutConstraint.activate([ pathView.leadingAnchor.constraint(equalTo: view.leadingAnchor), pathView.trailingAnchor.constraint(equalTo: view.trailingAnchor), pathView.topAnchor.constraint(equalTo: view.topAnchor), pathView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) pathView.backgroundColor = .clear let path = UIBezierPath() path.move(to: CGPoint(x: 10, y: 10)) path.addLine(to: CGPoint(x: 100, y: 100)) path.lineWidth = 3 pathView.path = path 

    Above, I add PathView programmatically, but you can also add it through IB and just set its path programmatically.

+179
May 30 '13 at 22:19
source share
— -

Create a UIView and add it as a subtitle of your view controller view. You can change this height or width of the candlestick to be very small so that it looks like a line. If you need to draw a diagonal line, you can change the subviews transform property.

eg. black horizontal line. This is called from your view controller implementation

UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)]; lineView.backgroundColor = [UIColor blackColor]; [self.view addSubview:lineView];

+12
May 30 '13 at 21:53
source share

Here you can find a useful technique: Using blocks to draw to avoid subclassing in Objective-C

Include a subclass of the general-purpose class in your project, then this is the code that you can add to your view controller to create an on-the-fly view that draws a line:

 DrawView* drawableView = [[[DrawView alloc] initWithFrame:CGRectMake(0,0,320,50)] autorelease]; drawableView.drawBlock = ^(UIView* v,CGContextRef context) { CGPoint startPoint = CGPointMake(0,v.bounds.size.height-1); CGPoint endPoint = CGPointMake(v.bounds.size.width,v.bounds.size.height-1); CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor); CGContextSetLineWidth(context, 1); CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5); CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5); CGContextStrokePath(context); }; [self.view addSubview:drawableView]; 
+8
May 31 '13 at 5:12
source share

You can use UIImageView to draw strings.

However, it allows you to skip a subclass. And since I'm a bit prone to Core Graphics, it can still use it. You can just put it in - ViewDidLoad

  UIGraphicsBeginImageContext(self.view.frame.size); [self.myImageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush); CGContextMoveToPoint(UIGraphicsGetCurrentContext(), 50, 50); CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), 200, 200); CGContextStrokePath(UIGraphicsGetCurrentContext()); CGContextFlush(UIGraphicsGetCurrentContext()); self.myImageView.image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

Addition to Rob's answer. For a quick third approach, you should use UIImageView - hide it - xib view. (This looks like the default UIImageView when dragging to xib in xcode 5)

Greetings and +1!

+6
Aug 22 '14 at 6:43
source share

Swift 3:

 let path = UIBezierPath() path.move(to: CGPoint(x: 10, y: 10)) path.addLine(to: CGPoint(x: 100, y: 100)) let shapeLayer = CAShapeLayer() shapeLayer.path = path.cgPath shapeLayer.strokeColor = UIColor.blue.cgColor shapeLayer.lineWidth = 3.0 view.layer.addSublayer(shapeLayer) 
+6
Jan 28 '17 at 22:37
source share

You really shouldn't, but if for some reason this makes sense to you, you can create a subclass of UIView, for example, DelegateDrawView, which accepts a delegate that implements a method like

 - (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect 

and then in the methods - [DelegateDrawView drawRect:] you call your delegation method.

But why do you want to put the view code in your controller.

You better create a subclass of UIView that draws a line between its two corners, you can have the property to set which two and then position the view where you want it to display the controller.

+2
May 30 '13 at 23:41
source share

To draw inside your view is very simple, @ Mr.ROB said that 2 methods I took the first method.

Just copy the code where you want it.

 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; startingPoint = [touch locationInView:self.view]; NSLog(@"Touch starting point = x : %f Touch Starting Point = y : %f", touchPoint.x, touchPoint.y); } -(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { } -(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; touchPoint = [touch locationInView:self.view]; NSLog(@"Touch end point =x : %f Touch end point =y : %f", touchPoint.x, touchPoint.y); } -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { UITouch *touch = [[event allTouches] anyObject]; touchPoint = [touch locationInView:self.view]; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)]; [path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)]; startingPoint=touchPoint; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [path CGPath]; shapeLayer.strokeColor = [[UIColor blueColor] CGColor]; shapeLayer.lineWidth = 3.0; shapeLayer.fillColor = [[UIColor redColor] CGColor]; [self.view.layer addSublayer:shapeLayer]; NSLog(@"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y); [self.view setNeedsDisplay]; } - (void)tapGestureRecognizer:(UIGestureRecognizer *)recognizer { CGPoint tappedPoint = [recognizer locationInView:self.view]; CGFloat xCoordinate = tappedPoint.x; CGFloat yCoordinate = tappedPoint.y; NSLog(@"Touch Using UITapGestureRecognizer x : %fy : %f", xCoordinate, yCoordinate); } 

It will be drawn as a line where the finger moves.

+1
Jan 09 '16 at 5:40
source share



All Articles