En primer lugar, para dibujar en IOS que necesitan un contexto y al dibujar en la pantalla no se puede conseguir el contexto exterior de drawRect:
(UIView) o drawLayer:inContext:
(CALayer). Esto significa que la opción 3 está fuera (si tu intención fue hacerlo fuera del método drawRect:
).
Podrías conseguir un CALayer, pero iría por una UIView aquí. Por lo que yo he entendido su configuración, usted tiene esto:
UIScrollView
| | |
ViewA ViewB LineView
Así LineView es un hermano de viewa y ViewB, habría que ser lo suficientemente grande como para cubrir tanto viewa y ViewB y está dispuesto para estar frente a tanto (y tiene setOpaque:NO
conjunto).
La implementación de LineView sería bastante directa: le daría dos propiedades point1
y point2
de tipo CGPoint. Opcionalmente, implemente los métodos setPoint1:
/setPoint2:
, por lo que siempre llama al [self setNeedsDisplay];
, por lo que se redibuja una vez que se ha cambiado un punto.
En LineView drawRect:
, todo lo que necesita es trazar la línea ya sea con CoreGraphics o con UIBezierPath. Cuál usar es más o menos una cuestión de gusto. Cuando te gusta usar CoreGraphics, lo haces de esta manera:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
// Set up color, line width, etc. first.
CGContextMoveToPoint(context, point1);
CGContextAddLineToPoint(context, point2);
CGContextStrokePath(context);
}
Usando NSBezierPath, se vería bastante similar:
- (void)drawRect:(CGRect)rect
{
UIBezierPath *path = [UIBezierPath bezierPath];
// Set up color, line width, etc. first.
[path moveToPoint:point1];
[path addLineToPoint:point2];
[path stroke];
}
La magia es ahora conseguir las coordenadas correctas para puntos 1 y 2.. Supongo que tienes un controlador que puede ver todas las vistas. UIView tiene dos buenos métodos de utilidad, convertPoint:toView:
y convertPoint:fromView:
que necesitará aquí. Aquí hay código ficticio para el controlador que causaría la LineView para dibujar una línea entre los centros de viewa y 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
}
Ya que no sé cómo se ha implementado el arrastre no te puedo decir cómo para disparar llamando a este método en el controlador. Si está completamente encapsulado en sus vistas y el controlador no está involucrado, buscaría una NSNotificación que publique cada vez que la vista se arrastre a una nueva coordenada.El controlador escucharía la notificación y llamaría al método antes mencionado para actualizar LineView.
Una última nota: es posible que desee llamar al setUserInteractionEnabled:NO
en su LineView en su método initWithFrame:
para que un toque en la línea pase a la vista debajo de la línea.
Happy coding!
+1 para el enfoque más eficiente, pero calcular la posición correcta y la transformación es más difícil que con la solución de dibujo simple (UIView o CALayer). Dado dos puntos * p1 * y * p2 *, ¿cómo posiciona/gira la capa correctamente? Tengo algunas ideas, pero ninguna me parece "correcta". – DarkDust
@DarkDust Se agregó un código para mostrar cómo establecer las propiedades de las capas. –
@Niklai Ruhe: Gracias, eso es incluso más simple de lo que pensaba. – DarkDust