У меня есть 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 to your project's "Link Binary with Libraries" и импортировать
<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/раскадровки или зрения , или вы можете программным способом добавить ваш контроллер просмотра в качестве подсмотра:
PathView *pathView = [[PathView alloc] initWithFrame:self.view.bounds]; pathView.backgroundColor = [UIColor clearColor]; [self.view addSubview: pathView];
Свифта исполнениями двух вышеуказанных подходов заключаются в следующем:
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
программно.
Awesome. Спасибо за тщательный ответ. – mkc842
Большое вам спасибо. Был поиск вашего ответа в течение нескольких дней. – eneskaya
@Rob: Это работает отлично. Я хочу спросить вас, что у меня есть расстояние по прямой AB и угол от AB, а затем, как получить начальную и конечную точки в этой ситуации? Пожалуйста, помогите мне. – Manthan
Создайте UIView и добавьте его в качестве подзаголовка вашего представления контроллера. Вы можете изменить высоту или ширину этого подвью, чтобы они были очень маленькими, чтобы она выглядела как линия. Если вам нужно нарисовать диагональную линию, вы можете изменить свойство преобразования subviews.
например. черную горизонтальную линию. Это вызывается из реализации вашей точки зрения контроллера
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.frame.size.width, 1)]; lineView.backgroundColor = [UIColor blackColor]; [self.view addSubview:lineView];
Может быть, ужасная идея, но она работает и проста. – sangony
Я был бы склонен согласиться с тем, что для разделительного элемента (например, линии между элементами UI) это путь наименьшего сопротивления. Альтернатива либо рендеринга в растровое изображение для поддержки слоя CoreAnimation, либо реализация обработчика рисования в пользовательском представлении гораздо более активна. Вероятно, аппаратное ускорение также улучшается, если только одна строка. – marko
интересная мысль, спасибо – mkc842
Вы не должны действительно, но если по какой-то причине это имеет смысл для вас, вы можете создать подкласс UIView, который называется DelegateDrawView, например, который принимает делегат, который реализует метод, как
- (void)delegateDrawView:(DelegateDrawView *)aDelegateDrawView drawRect:(NSRect)dirtyRect
, а затем в методах - [DelegateDrawView drawRect:] вы вызываете свой метод делегирования.
Но почему вы хотите поместить код просмотра в свой контроллер.
Вам лучше создать подкласс UIView, который рисует линию между двумя его углами, вы можете иметь свойство устанавливать, какие два, а затем позиционировать вид, где вы хотите, чтобы вы видели контроллер.
Вот крутая техника, которую вы могли бы оказаться полезными: Using blocks for drawing to avoid subclassing in Objective-C
Включить общего назначения вида подкласса артикля в проекте, то это своего рода код, который вы можете поместить в ваш контроллер представления, чтобы создать вид на fly, который рисует линию:
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();
Дополнение к ответу Роба Для Quicke, третий подход заключается в использовании UIImageView
- прикрывать с ней - вид XIb. (Это вид UIImageView по умолчанию при перетаскивании на xib в xcode 5)
Приветствия и +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);
}
Он будет рисовать, как линии, где палец движется не собирается
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)
Это здорово! Спасибо. – Zhanserik
- 1. Программно получить экземпляр контроллера вида
- 2. Программно изменяемый класс контроллера вида просмотра (быстрый)
- 3. Как установить вид программно созданного контроллера вида на SKView?
- 4. Изменение вида с контроллера
- 5. Программно добавляя представления к представлению контроллера вида с помощью AutoLayout
- 6. переменная доступа контроллера вида с контроллера толкаемого вида
- 7. reloading tableView одного контроллера вида с контроллера толкаемого вида
- 8. удаление какого-либо вида с контроллера вида
- 9. Как вы создаете «заголовок» для контроллера вида просмотра 3D-изображения?
- 10. Как вы рисуете линию с границы?
- 11. Форсирование ориентации контроллера вида
- 12. Сделайте экземпляр контроллера вида и выделите его программно
- 13. iOS установка переменной вида из контроллера представления программно
- 14. Настройка контроллера вида с бортовыми
- 15. Странность с рамкой контроллера вида
- 16. Программно добавляя два контроллера представления в два вида контейнера
- 17. Как представить контроллер вида с другого контроллера вида
- 18. Как запустить контроллер вида с другого контроллера?
- 19. Как вызвать метод с другого контроллера вида
- 20. как вызвать файл вида с контроллера (cakePHP)
- 21. Новичок: как UITableView программно с другого вида
- 22. Как разделить экран контроллера вида?
- 23. Как получить имя контроллера вида?
- 24. UITableView внутри контроллера вида
- 25. Подклассификация контроллера вида
- 26. Изменение свойств контроллера вида из другого контроллера вида
- 27. Инициализация контроллера вида
- 28. Отклонение контроллера вида навигации
- 29. Создание вида и контроллера
- 30. Назначение вида переменной программно
Нет, вы не можете. Рисование должно выполняться по представлению, а не по контроллеру. Вы должны изменить свой дизайн. –
@xlc Вы можете сделать это с VC, как показывает ответ Роба. Если вы действительно хотите быть полезными, объясните, в чем вред в технике Безье. – mkc842
«Закрыто как не настоящий вопрос». «Трудно сказать, что здесь задают». «Не может быть разумного ответа». Ну и шутка! Вопрос совершенно ясен, и у Роба, похоже, не было никаких проблем с его ответом. Если у вас возникла проблема с моим вопросом, почему бы не объяснить вашу проблему, а не закрыть ее на явно ложных основаниях? – mkc842