首先,在iOS上进行绘图需要一个上下文,当在屏幕上绘制时,你无法在
drawRect:
(UIView)或
drawLayer:inContext:
(CALayer)之外获取上下文。这意味着选项3不可行(如果你打算在
drawRect:
方法之外执行它)。
你可以选择使用CALayer,但我建议在这里使用UIView。就我所理解的设置而言,你有这个:
UIScrollView
| | |
ViewA ViewB LineView
所以,LineView是ViewA和ViewB的兄弟视图,需要足够大以覆盖两个视图,并排列在两者前面(并设置了
setOpaque:NO
)。
LineView的实现非常简单:给它两个类型为CGPoint的属性
point1
和
point2
。选择性地,自己实现
setPoint1:
/
setPoint2:
方法,以便每次更改点时始终调用
[self setNeedsDisplay];
,从而重新绘制自身。
在LineView的
drawRect:
中,你只需要使用
CoreGraphics或
UIBezierPath之一来绘制线条。要使用哪个更多或少是品味问题。当你想使用CoreGraphics时,可以像这样做:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, point1);
CGContextAddLineToPoint(context, point2);
CGContextStrokePath(context);
}
使用NSBezierPath,看起来非常相似:
- (void)drawRect:(CGRect)rect
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:point1];
[path addLineToPoint:point2];
[path stroke];
}
现在的关键是获取点1和点2的正确坐标。我假设你有一个可以查看所有视图的控制器。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));
p1 = [scrollView convertPoint:p1 fromView:viewA];
p2 = [scrollView convertPoint:p2 fromView:viewB];
p1 = [scrollView convertPoint:p1 toView:lineView];
p2 = [scrollView convertPoint:p2 toView:lineView];
[lineView setPoint1:p1];
[lineView setPoint2:p2];
[lineView setNeedsDisplay];
}
由于我不知道您是如何实现拖动的,因此无法告诉您如何在控制器上调用此方法。如果完全封装在视图中且控制器未涉及,则应该使用 NSNotification,每次视图拖动到新坐标时会发布一次通知。控制器将侦听通知并调用上述方法来更新 LineView。
最后一点提示:在 LineView 的initWithFrame:
方法中,您可能希望调用 setUserInteractionEnabled:NO
,以便触摸线条时可以穿过线条到达线条下方的视图。
祝编码愉快!
UIViewEdgeAntialiasing
来为核心动画层打开抗锯齿功能。 - Nikolai Ruhe