У меня есть UIViewController
. Как нарисовать линию в одном из программно созданных представлений?
ios
objective-c
uiview
uikit
mkc842
источник
источник
Ответы:
Есть два распространенных метода.
Использование
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); }
Он будет рисовать как линию, по которой движется палец
источник