У меня есть UIViewController
. Как нарисовать линию в одном из программно созданных представлений?
У меня есть UIViewController
. Как нарисовать линию в одном из программно созданных представлений?
Ответы:
Есть два распространенных метода.
Использование 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 файл, но в этом больше нет необходимости (если у вас есть «Включить модули» и «Связать Frameworks "Автоматически" включены настройки сборки).
Другой подход - создать подкласс, 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];
Представления 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 и добавьте его как часть представления вашего контроллера представления. Вы можете изменить высоту или ширину этого подвида, сделав его очень маленьким, чтобы он выглядел как линия. Если вам нужно нарисовать диагональную линию, вы можете изменить свойство преобразования вложенных представлений.
например, нарисуйте черную горизонтальную линию. Это вызывается из реализации вашего контроллера представления
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[self.view addSubview:lineView];
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)
Вот классная техника, которая может вам пригодиться: использование блоков для рисования, чтобы избежать создания подклассов в 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();
В дополнение к ответу Роба, третий подход - использовать UIImageView
- прикрыть его - представлением xib. (Это внешний вид UIImageView по умолчанию при перетаскивании на xib в xcode 5)
Ура и +1!
На самом деле вы этого не должны, но если по какой-то причине это имеет для вас смысл, вы можете создать подкласс UIView, DelegateDrawView
например, вызываемый , который принимает делегат, который реализует такой метод, как
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
а потом в методах - [DelegateDrawView drawRect:]
вы должны вызвать свой метод делегата.
Но зачем вам помещать код представления в свой контроллер?
Вам лучше создать подкласс UIView, который рисует линию между двумя своими углами, вы можете иметь свойство, чтобы установить, какие два, а затем расположить представление там, где вы хотите, от контроллера представления.
Рисовать внутри вашего представления очень просто, @ 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);
}
Он будет рисовать как линию, по которой движется палец