Во-первых, для рисования на iOS вам нужен контекст, а при рисовании на экране вы не можете получить контекст за пределами drawRect:
(UIView) или drawLayer:inContext:
(CALayer). Это означает, что вариант 3 отсутствует (если вы намеревались сделать это вне метода drawRect:
).
Вы могли бы пойти на CALayer, но я бы пошел на UIView здесь. Насколько я понял ваши настройки, у вас есть это:
UIScrollView
| | |
ViewA ViewB LineView
Таким образом, LineView является родственным элементом ViewA и ViewB, он должен быть достаточно большим, чтобы охватить как ViewA, так и ViewB, и должен располагаться перед обоими (и имеет setOpaque:NO
set).
Реализация LineView будет довольно простой: дать ей два свойства point1
и point2
типа CGPoint. По желанию, реализуйте методы setPoint1:
/ setPoint2:
самостоятельно, чтобы он всегда вызывал [self setNeedsDisplay];
, поэтому он перерисовывается после изменения точки.
В LineView drawRect:
все, что вам нужно, это нарисовать линию либо с CoreGraphics , либо с UIBezierPath . Какой из них использовать, более или менее дело вкуса. Когда вам нравится использовать CoreGraphics, вы делаете это так:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
// Set up color, line width, etc. first.
CGContextMoveToPoint(context, point1);
CGContextAddLineToPoint(context, point2);
CGContextStrokePath(context);
}
Используя NSBezierPath, это выглядело бы очень похоже:
- (void)drawRect:(CGRect)rect
{
UIBezierPath *path = [UIBezierPath bezierPath];
// Set up color, line width, etc. first.
[path moveToPoint:point1];
[path addLineToPoint:point2];
[path stroke];
}
Магия теперь получает правильные координаты для point1 и point2. Я предполагаю, что у вас есть контроллер, который может видеть все виды. В UIView есть два полезных служебных метода: convertPoint:toView:
и convertPoint:fromView:
, которые вам понадобятся здесь. Вот фиктивный код для контроллера, который заставит LineView нарисовать линию между центрами ViewA и ViewB:
- (void)connectTheViews
{
CGPoint p1, p2;
CGRect frame;
frame = [viewA frame];
p1 = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
frame = [viewB frame];
p2 = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
// Convert them to coordinate system of the scrollview
p1 = [scrollView convertPoint:p1 fromView:viewA];
p2 = [scrollView convertPoint:p2 fromView:viewB];
// And now into coordinate system of target view.
p1 = [scrollView convertPoint:p1 toView:lineView];
p2 = [scrollView convertPoint:p2 toView:lineView];
// Set the points.
[lineView setPoint1:p1];
[lineView setPoint2:p2];
[lineView setNeedsDisplay]; // If the properties don't set it already
}
Поскольку я не знаю, как вы реализовали перетаскивание, я не могу сказать вам, как вызвать вызов этого метода на контроллере. Если это сделано полностью инкапсулированным в ваших представлениях, а контроллер не задействован, я бы использовал NSNotification, которое вы публикуете каждый раз, когда представление перетаскивается в новую координату. Контроллер прослушивает уведомление и вызывает вышеупомянутый метод для обновления LineView.
Последнее замечание: вы можете вызвать setUserInteractionEnabled:NO
для вашего LineView в его методе initWithFrame:
, чтобы прикосновение к линии проходило до вида под линией.
Удачного кодирования!