2011-12-29 13 views
15

En resumen:ajuste de marco correcto de un recién creado CAShapeLayer

  1. de Apple no establece el frame o bounds para un CAShapeLayer automáticamente (y Apple no ha implementado un equivalente de [UIView sizeThatFits])
  2. Si se establece el marco usando el tamaño del cuadro delimitador de la ruta ... todo sale mal. No importa cómo se intenta establecer que, se atornilla en marcha la Ruta

Así que, ¿cuál es la forma correcta de establecer mediante programación el marco de un recién creado CAShapeLayer con un recién añadido CGPath? Los documentos de Apple no dicen nada al respecto.

cosas I han intentado, que no funcionan:

  1. Crear una CAShapeLayer
  2. Crear una CGPath, añadirlo a la capa
  3. de Check frame la capa - es {{0,0},{0,0}}
  4. Set: layer.frame = CGPathGetBoundingBox(layer.path)
  5. El marco ahora es correcto, pero la ruta ahora es DOBLE desplazamiento - cambiando el frame hace que el camino que se ha desplazado efectivamente un extra de (x,y) píxeles

  6. Set: layer.bounds = CGPathGetBoundingBox(layer.path)

  7. ... todo se vuelve loco. Nada tiene sentido más
  8. Intente solucionarlo haciendo layer.position = CGPathGetBoundingBox(layer.path).origin
  9. ... no dice; todavía loco

Una cosa que he intentado que funcionaba, pero causa problemas en otra parte:

EDIT: Esto rompe tan pronto como se auto-rotación de la pantalla. Mi suposición: la auto-rotación de Apple requiere el control de la propiedad "transformar".

  1. Crear un CAShapeLayer
  2. Crear una CGPath, añadirlo a la capa
  3. Compruebe marco de la capa - es {{0,0},{0,0}}
  4. Set: layer.frame = CGPathGetBoundingBox(layer.path)
  5. Set: layer.transform = CGAffineTransformMakeTranslation(CGPathGetBoundingBox(layer.path).origin.x * -1, // same for y-coord: set it to "-1 * the path's origin

Este funciona, pero ... muchos códigos de terceros asumen que la transformación inicial f o CALayer es Identidad.

¡No debería ser tan difícil! Seguramente hay algo que estoy haciendo mal aquí?

(He recibido una sugerencia: "cada vez que agrega una ruta, ejecute manualmente una función personalizada para cambiar todos los puntos por -1 * (top-left-point.x, top-left-point.y)".De nuevo, eso funciona, pero es ridículamente complejo)

+0

¿Alguna vez encontró una solución para esto? – jannej

+0

Aún no. Actualmente estoy usando la solución de la pregunta en sí. Es lento y es un dolor de mantener. Creo que el problema es un error en el código de Apple, tal vez? – Adam

+3

Una pequeña adición: finalmente descubrí que ".frame" no es compatible con Apple. Esto es extraño, porque se usa en todas partes, pero si profundizas lo suficiente en los documentos y/o en las listas de correo de Apple, descubres notas de los ingenieros de Apple que dicen que no está diseñado para funcionar y que no corregirán errores con él. Se espera/se requiere que use .bounds para TODO, y trate .frame como "readonly". Por lo tanto, es especialmente irónico que en este caso, el ajuste .frame "casi funciona", donde el establecimiento de .bounds "nunca funciona" :) – Adam

Respuesta

4

Establecer layer.bounds en los límites de la ruta es lo correcto: desea que el espacio de coordenadas local de la capa coincida con la ruta. Pero también debes establecer la propiedad de posición de la capa para moverla al lugar correcto en su superlayer.

(Setting .frame se traduce en el framework calculando los valores correctos de .bounds y .position para usted, pero siempre deja intactos los bounds.origin, que no es lo que quiere cuando su path bounds tiene un origen distinto de cero .)

así que algo como esto debería funcionar, suponiendo que no haya cambiado la Anchorpoint de su valor habitual (0.5, 0.5) y desea colocar la capa ras con el origen de su superlayer:

CGRect r = CGPathGetBoundingBox(layer.path); 
layer.bounds = r; 
layer.position = CGPointMake(r.size.width*.5, r.size.height*.5); 
Cuestiones relacionadas