我有一个UIViewController
。如何在其以编程方式创建的视图之一中画线?
我有一个UIViewController
。如何在其以编程方式创建的视图之一中画线?
Answers:
有两种常用技术。
使用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添加到项目的“使用库链接二进制<QuartzCore/QuartzCore.h>
文件”,并将标头导入到.m文件中,但这不再是必须的(如果您具有“启用模块”和“链接”自动打开框架”构建设置)。
另一种方法是子类化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 / storyboard或视图的基类,或者可以让视图控制器以编程方式将其添加为子视图:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds];
pathView.backgroundColor = [UIColor clearColor];
[self.view addSubview: pathView];
上面两种方法的Swift演绎如下:
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)
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
编程方式进行设置即可。
shapeLayer.lineCap = kCALineCapRound;
UIBezierPath
重复的addLineToPoint
/addLine(to:)
调用。然后,您可以选择喜欢 shapeLayer.lineJoin = kCALineJoinRound
还是kCALineJoinBevel
或kCALineJoinMiter
。
创建一个UIView并将其添加为视图控制器视图的子视图。您可以将该子视图的高度或宽度修改得很小,以使其看起来像一条线。如果需要绘制对角线,则可以修改子视图的transform属性。
例如画一条黑色的水平线。这是在您的视图控制器的实现中调用的
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];
斯威夫特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)
这是一个很酷的技术,您可能会发现它有用:使用绘图块避免在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];
您可以使用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!
您本不应该这样,但是如果出于某种原因对您有意义,则可以创建UIView的子类(DelegateDrawView
例如,称为),该子类需要一个委托,该委托实现了类似
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
然后在方法中-[DelegateDrawView drawRect:]
您应该调用委托方法。
但是,为什么要在控制器中放置视图代码。
最好创建一个UIView的子类,该子类在它的两个角之间画一条线,可以有一个属性来设置哪两个,然后将其放置在视图控制器中所需的位置。
要画出您的视图非常简单,@ 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);
}
它会画一条线,手指移动