NSAttributedString color de background y esquinas networkingondeadas

Tengo una pregunta sobre las esquinas networkingondeadas y el color de background del text para una UIView personalizada.

Básicamente, necesito lograr un efecto como este (image adjunta, observa las esquinas networkingondeadas en un lado) en una UIView personalizada: Destacado de fondo

Estoy pensando que el enfoque para usar es:

  • Usa el text principal para get carreras de glifos.
  • Verifique el range de resaltado.
  • Si la ejecución actual está dentro del range de resaltado, dibuje un rectángulo de background con esquinas networkingondeadas y el color de relleno deseado antes de dibujar la ejecución del glifo.
  • Dibuja la carrera del glifo.

Sin embargo, no estoy seguro de si esta es la única solución (o para el caso, si esta es la solución más eficiente).

Usar una UIWebView no es una opción, así que tengo que hacerlo en una UIView personalizada.

Mi pregunta es, ¿es este el mejor enfoque para usar, y estoy en el path correcto? ¿O estoy perdiendo algo importante o haciéndolo mal?

¡Gracias de antemano por su ayuda! 🙂

¡Aclamaciones!

Logré lograr el efecto anterior, así que pensé que publicaría una respuesta para el mismo.

Si alguien tiene alguna sugerencia acerca de hacer esto más efectivo, siéntase libre de contribuir. Me aseguraré de marcar tu respuesta como la correcta. 🙂

Para hacer esto, deberá agregar un "atributo personalizado" a NSAttributedString .

Básicamente, lo que eso significa es que puede agregar cualquier par de valor-key, siempre y cuando sea algo que pueda agregar a una instancia de NSDictionary . Si el sistema no reconoce ese atributo, no hace nada. Depende de usted, como desarrollador, proporcionar una implementación y un comportamiento personalizados para ese atributo.

A los efectos de esta respuesta, supongamos que he agregado un atributo personalizado llamado: @"MyRoundedBackgroundColor" con un valor de [UIColor greenColor] .

Para los pasos que siguen, necesitará tener una comprensión básica de cómo CoreText hace las cosas. Consulte la Guía de progtwigción de text principal de Apple para comprender qué es una ejecución / glyph de frame / line / glyph, etc.

Entonces, estos son los pasos:

  1. Cree una subclass UIView personalizada.
  2. Tener una propiedad para aceptar una NSAttributedString .
  3. Cree un CTFramesetter utilizando esa instancia NSAttributedString .
  4. Anular el drawRect: método
  5. Cree una instancia de CTFrame desde CTFramesetter .
    1. Deberá proporcionar un CGPathRef para crear el CTFrame . Haga que CGPath sea ​​el mismo que el marco en el que desea dibujar el text.
  6. Obtenga el context de charts actual y active el sistema de coorderadas de text.
  7. Usando CTFrameGetLines(...) , obtenga todas las líneas en el CTFrame que acaba de crear.
  8. Usando CTFrameGetLineOrigins(...) , obtenga todos los orígenes de línea para el CTFrame .
  9. Inicie un for loop : para cada línea del set de CTLine
  10. Establezca la position del text al comienzo de CTLine usando CGContextSetTextPosition(...) .
  11. Usando CTLineGetGlyphRuns(...) obtén todos los Glyph Runs ( CTRunRef ) de CTLine .
  12. Comience otro for loop : para cada glyphRun en la matriz de CTRun
  13. Obtenga el range de la ejecución usando CTRunGetStringRange(...) .
  14. Obtenga límites tipocharts mediante CTRunGetTypographicBounds(...) .
  15. Obtenga el desplazamiento x para la ejecución utilizando CTLineGetOffsetForStringIndex(...) .
  16. Calcule el rectángulo delimitador (llamémoslo runBounds ) usando los valores devueltos de las funciones mencionadas anteriormente.
    1. Recuerde: CTRunGetTypographicBounds(...) requiere pointers a las variables para almacenar el "ascenso" y "descenso" del text. Debe agregarlos para get la altura de ejecución.
  17. Obtenga los attributes para la ejecución con CTRunGetAttributes(...) .
  18. Compruebe si el dictionary de attributes contiene su atributo.
  19. Si su atributo existe, calcule los límites del rectángulo que necesita pintarse.
  20. El text principal tiene los orígenes de la línea en la línea de base. Debemos dibujar desde el punto más bajo del text hasta el punto más alto. Por lo tanto, debemos ajustar para el descenso.
  21. Por lo tanto, reste el descenso del rectángulo delimitante que calculamos en el paso 16 ( runBounds ).
  22. Ahora que tenemos runBounds , sabemos qué área queremos pintar, ahora podemos usar cualquiera de los methods UIBezierPath / UIBezierPath para dibujar y rellenar un rectángulo con esquinas networkingondeadas específicas.
    1. UIBezierPath tiene un método de class de conveniencia llamado bezierPathWithRoundedRect:byRoundingCorners:cornerRadii: eso le permite bezierPathWithRoundedRect:byRoundingCorners:cornerRadii: esquinas específicas. Usted especifica las esquinas usando máscaras de bits en el segundo parámetro.
  23. Ahora que ha llenado el rectángulo, simplemente dibuje el glifo ejecutado usando CTRunDraw(...) .
  24. Celebre la victoria por haber creado su atributo personalizado: ¡beba una cerveza o algo así! :RE

En cuanto a la detección de que el range de attributes se extiende a través de varias ejecuciones, puede get el range efectivo completo de su atributo personalizado cuando la primera ejecución encuentra el atributo. Si encuentra que la longitud del scope efectivo máximo de su atributo es mayor que la duración de su carrera, necesita pintar esquinas agudas en el lado derecho (para un script de izquierda a derecha). Más matemáticas le permitirá detectar el estilo de esquina de resaltado para la siguiente línea también. 🙂

Adjunto hay una captura de pantalla del efecto. El recuadro en la parte superior es un UITextView estándar, para el que he configurado el text atribuido. El cuadro en la parte inferior es el que se ha implementado utilizando los pasos anteriores. La misma cadena atribuida se ha establecido para ambas textViews. atributo personalizado con esquinas redondeadas

Una vez más, si hay un enfoque mejor que el que he usado, ¡hágamelo saber! :RE

Espero que esto ayude a la comunidad. 🙂

¡Aclamaciones!