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

mkc*_*842 80 objective-c uikit uiview ios

我有一个UIViewController.我想在其中一个以编程方式创建的视图中绘制一条线.看起来很简单,但我还没有找到有效的示例代码.

Rob*_*Rob 181

有两种常见的技术.

  1. 使用CAShapeLayer:

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

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

      CAShapeLayer *shapeLayer = [CAShapeLayer layer];
      shapeLayer.path = [path CGPath];
      shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
      shapeLayer.lineWidth = 3.0;
      shapeLayer.fillColor = [[UIColor clearColor] CGColor];
      
      Run Code Online (Sandbox Code Playgroud)
    • 将其添加CAShapeLayer到视图的图层:

      [self.view.layer addSublayer:shapeLayer];
      
      Run Code Online (Sandbox Code Playgroud)

    在以前版本的Xcode中,您必须手动将QuartzCore.framework添加到项目的"Link Binary with Libraries"并导入<QuartzCore/QuartzCore.h>.m文件中的标题,但这不再是必需的(如果您有"启用模块"和"链接"框架自动"打开构建设置".

  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);
      }
      
      Run Code Online (Sandbox Code Playgroud)

      或使用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];
      }
      
      Run Code Online (Sandbox Code Playgroud)
    • 然后,您可以将此视图类用作NIB /故事板或视图的基类,也可以让视图控制器以编程方式将其添加为子视图:

      PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
      pathView.backgroundColor = [UIColor clearColor];
      
      [self.view addSubview: pathView];
      
      Run Code Online (Sandbox Code Playgroud)

上述两种方法的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)
    
    Run Code Online (Sandbox Code Playgroud)
  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()
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    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
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 真棒.谢谢你彻底的答复. (3认同)
  • @Rob:这工作得很好。我想问一下,我有直线距离AB和与AB的角度,那么在这种情况下如何获得起点和终点?请帮我。 (2认同)

Jef*_*mes 13

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

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

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

  • 我很好奇为什么这是一个可怕的想法的原因.我想避免在我自己的代码中这个解决方案可能导致的任何问题. (4认同)

Pie*_*ton 8

这是一个很有用的技巧:使用块进行绘制以避免在Objective-C中进行子类化

在项目中包含文章的通用视图子类,然后这是您可以在视图控制器中创建一个绘制线条的视图的代码:

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];
Run Code Online (Sandbox Code Playgroud)


Bar*_*baa 8

斯威夫特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)
Run Code Online (Sandbox Code Playgroud)


khu*_*han 6

您可以使用UIImageView绘制线条.

但是,它允许跳过子类.因为我不太倾向于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();
Run Code Online (Sandbox Code Playgroud)

除了Rob的答案,对于一个快车,第三种方法是使用UIImageView- 掩盖它 - xib的视图.(这是在xcode 5中拖动xib时的默认UIImageView外观)

干杯和+1!