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

时间:2013-05-30 21:47:00

标签: ios objective-c uiview uikit

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

8 个答案:

答案 0 :(得分:179)

有两种常用技巧。

  1. 使用CAShapeLayer

    • 创建UIBezierPath(用您想要的任何内容替换坐标):

      UIBezierPath *path = [UIBezierPath bezierPath];
      [path moveToPoint:CGPointMake(10.0, 10.0)];
      [path addLineToPoint:CGPointMake(100.0, 100.0)];
      
    • 创建使用CAShapeLayer的<{1}}:

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

      CAShapeLayer

    在以前版本的Xcode中,您必须手动添加QuartzCore.framework to your project's "Link Binary with Libraries"并在.m文件中导入[self.view.layer addSublayer:shapeLayer]; 标题,但这不再是必需的(如果您有“启用模块”和“链接框架自动“打开构建设置”。

  2. 另一种方法是继承<QuartzCore/QuartzCore.h>,然后在CoreGraphics方法中使用drawRect次调用:

    • 创建一个UIView子类并定义一个用于绘制线条的UIView

      您可以使用Core Graphics执行此操作:

      drawRect

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

      - (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];
      }
      

  3. 上述两种方法的Swift演绎​​如下:

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

      CAShapeLayer
    2. // 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) 子类:

      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 ,但您也可以通过IB添加它,只需以编程方式设置PathView

答案 1 :(得分:12)

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

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

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

答案 2 :(得分:8)

这是一种很有用的技巧:Using blocks for drawing to avoid subclassing in 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];

答案 3 :(得分: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();

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

欢呼和+1!

答案 4 :(得分:6)

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

答案 5 :(得分:2)

你不应该真的,但如果由于某种原因它对你有意义,你可以创建一个UIView的子类,例如,名为DelegateDrawView,它接受一个实现像

这样的方法的委托
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect

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

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

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

答案 6 :(得分:1)

在你的视图内部绘制非常简单,@ Mr.ROB说2方法我采取了第一种方法。

只需将代码粘贴到您想要的地方即可。

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

它会像一条线一样画出,手指在哪里移动

答案 7 :(得分:0)

斯威夫特 5.4

使用高度为 1 或 2 磅的 UIView 并将其添加为视图控制器视图的子视图。

class Separator: UIView {

    let line = UIView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
    }


    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func configure() {
        backgroundColor = .red

        addSubview(line)
        line.translatesAutoresizingMaskIntoConstraints = false
        line.backgroundColor = .secondaryLabelColor

        NSLayoutConstraint.activate([
            line.centerYAnchor.constraint(equalTo: self.centerYAnchor),
            line.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            line.heightAnchor.constraint(equalToConstant: Pad.separatorHeight),
            line.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.8 )
        ])
    }
}

然后将其添加到您的视图控制器中:


let separator = Separator()
view.addSubview(separator)
separator.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
    separator.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    separator.topAnchor.constraint(equalTo: view.bottomAnchor),
    separator.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    separator.heightAnchor.constraint(equalToConstant: 72.0)
    ])