ios 如何从视图控制器以编程方式绘制一条线?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16846413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:45:07  来源:igfitidea点击:

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

iosobjective-cuiviewuikit

提问by mkc842

I have a UIViewController. How do I draw a line in one of its programmatically created views?

我有一个UIViewController. 如何在其以编程方式创建的视图之一中绘制一条线?

回答by Rob

There are two common techniques.

有两种常用的技术。

  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 CAShapeLayerthat uses that UIBezierPath:

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

      [self.view.layer addSublayer:shapeLayer];
      

    In previous versions of Xcode, you had to manually add QuartzCore.framework to your project's "Link Binary with Libraries"and import the <QuartzCore/QuartzCore.h>header in your .m file, but that's not necessary anymore (if you have the "Enable Modules" and "Link Frameworks Automatically" build settings turned on).

  2. The other approach is to subclass UIViewand then use CoreGraphicscalls in the drawRectmethod:

    • Create a UIViewsubclass and define a drawRectthat 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];
      }
      
    • Then you can either use this view class as the base class for your NIB/storyboard or view, or you can have your view controller programmatically add it as a subview:

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

    • 创建一个UIBezierPath(用你想要的任何替换坐标):

      UIBezierPath *path = [UIBezierPath bezierPath];
      [path moveToPoint:CGPointMake(10.0, 10.0)];
      [path addLineToPoint:CGPointMake(100.0, 100.0)];
      
    • 创建一个CAShapeLayer使用它的UIBezierPath

      CAShapeLayer *shapeLayer = [CAShapeLayer layer];
      shapeLayer.path = [path CGPath];
      shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
      shapeLayer.lineWidth = 3.0;
      shapeLayer.fillColor = [[UIColor clearColor] CGColor];
      
    • 将其添加CAShapeLayer到您的视图层:

      [self.view.layer addSublayer:shapeLayer];
      

    在以前版本的 Xcode 中,您必须手动将QuartzCore.framework添加到项目的“Link Binary with Libraries”<QuartzCore/QuartzCore.h>在 .m 文件中导入标头,但这不再需要(如果您有“Enable Modules”和“Link框架自动”构建设置已打开)。

  2. 另一种方法是子类化UIView,然后在方法中使用CoreGraphics调用drawRect

    • 创建一个UIView子类并定义一个drawRect画线。

      你可以用 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);
      }
      

      或使用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];
      }
      
    • 然后你可以使用这个视图类作为你的 NIB/故事板或视图的基类,或者你可以让你的视图控制器以编程方式将它添加为子视图:

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


The Swift renditions of the two above approaches are as follows:

上述两种方法的 Swift 版本如下:

  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's layer:
    
    view.layer.addSublayer(shapeLayer)
    
  2. UIViewsubclass:

    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'm adding PathViewprogrammatically, but you can add it via IB, too, and just set its pathprogrammatically.

  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's layer:
    
    view.layer.addSublayer(shapeLayer)
    
  2. UIView子类:

    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()
        }
    
    }
    

    并将其添加到您的视图层次结构中:

    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
    

    上面,我以PathView编程方式添加,但您也可以通过 IB 添加它,只需以path编程方式设置它。

回答by Jeff Ames

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

创建一个 UIView 并将其添加为视图控制器视图的子视图。您可以将此子视图的高度或宽度修改为非常小,使其看起来像一条线。如果需要绘制对角线,可以修改 subviews 变换属性。

e.g. draw black horizontal line. This is called from within your view controller's implementation

例如绘制黑色水平线。这是从您的视图控制器的实现中调用的

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

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

回答by Pierre Houston

Here's a cool technique you might find useful: Using blocks for drawing to avoid subclassing in Objective-C

这里有一个很酷的技巧,你可能会觉得很有用:使用块进行绘图以避免在 Objective-C 中进行子类化

Include the article's general-purpose view subclass in your project, then this is the kind of code you can put in your view controller to create a view on the fly 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];

回答by Baraa Al-Tabbaa

Swift 3:

斯威夫特 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)

回答by khunshan

You can use UIImageView to draw lines on.

您可以使用 UIImageView 在其上绘制线条。

It however, allows to skip sub-classing. And as I am little inclined to Core Graphics still can use it. You can just put it in - ViewDidLoad

但是,它允许跳过子分类。而且由于我不太倾向于 Core Graphics 仍然可以使用它。你可以把它放进去——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 quicke, the third approach is to use an UIImageView- cover up with it - the view of xib. (Thats the default UIImageView appearance when dragged on xib in xcode 5)

除了 Rob 的回答,为了快速起见,第三种方法是使用UIImageView- 掩盖它 - xib 的视图。(这是在 xcode 5 中在 xib 上拖动时的默认 UIImageView 外观)

Cheers and +1!

干杯和+1!

回答by Nathan Day

You shouldn't really, but if for some reason it makes sense to you, you could create a subclass of UIView, called DelegateDrawViewfor example, that takes a delegate which implements a method like

你不应该真的,但如果出于某种原因它对你有意义,你可以创建一个 UIView 的子类,DelegateDrawView例如调用,它需要一个实现类似方法的委托

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

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

然后在方法中 -[DelegateDrawView drawRect:]你应该调用你的委托方法。

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

但是为什么要将视图代码放在控制器中。

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

你最好创建一个 UIView 的子类,在它的两个角之间画一条线,你可以有一个属性来设置哪两个角,然后将视图从视图控制器定位到你想要的位置。

回答by Kishore Kumar

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

在视图中绘制非常简单,@Mr.ROB 说两种方法我采用了第一种方法。

Just Copy paste the code where you guys 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 : %f y : %f", xCoordinate, yCoordinate);
}

It will draw like a line ,where the finger moves going

它会画一条线,手指移动的地方