2012-01-10 14 views
5

Lo que me gustaría hacer es crear un componente de contenedor de texto que pueda indicar cuál es la palabra más cercana cuando hay un toque en ella (es decir, la palabra "detrás" "el punto tocado".Cómo obtener la palabra tocada en una UILabel/UITextView

Primero, creé una subclase UILabel y anulé el método touchesEnded: withEvent: para determinar el CGPoint tocado. También escribí un método que calcula el "marco" correspondiente (CGRect) de cada palabra del texto usando sizeWithFont: forWidth: lineBreakMode :. Con el CGPoint tocado y este marco, puedo determinar qué palabra se está tocando en realidad. Pero el método que calcula el marco solo funciona con texto de una sola línea.

Así que ahora necesito saber qué parte del texto está en una línea determinada (es decir, cómo se ha dividido el texto), de modo que pueda calcular el margen izquierdo y el margen superior correcto de cada palabra.

¿Alguna idea de cómo puedo obtener esto? ¿O tal vez tiene una solución más directa para lograr esto? This post was unfortunately not very helpful... ...

Respuesta

9

(Hay un enlace a un proyecto de código de ejemplo en su entrada vinculada que contiene un código de ejemplo útil, pero voy a describir el proceso para que también en este caso.)

En resumen, van a necesitar utilizar Core Text, que es el marco avanzado de manejo de texto basado en C de Apple que respalda todo el diseño de texto sofisticado en iOS y OS X.

El código completo va a ser algo complicado, pero los métodos clave son vamos a querer ver son:

CTFramesetterCreateWithAttributedString() - use esto, en conj unction con un NSAttributedString que obtendrá del texto de su etiqueta: para crear el fotoconfigurador

CTFramesetterCreateFrame(): use esto para obtener un CTFrameRef para su texto del fotocortelador anterior. Deberá crear un CGPathRef usando los límites de su etiqueta para hacer esto.

CTFrameGetLines(), CTFrameGetLineOrigins() - Se usan para obtener CTLineRefs correspondientes a las líneas de composición tipográfica, y las coordenadas de los orígenes de las líneas, respectivamente, a continuación, utilizar CTLineGetStringIndexForPosition() para encontrar el índice de caracteres en una localización táctil.

Puede utilizar este índice de caracteres (en el marco de referencia de la línea) para retroceder y encontrar el carácter/palabra/etc real en su cadena completa.

No se olvide que las cosas se complican por un par de problemas:

  1. Si utiliza de UILabel dibujo tendrá que tener cuidado para adaptarse perfectamente a sus métricas de composición tipográfica, que puede ser engorroso ya que la mayoría de los nativos los objetos (por ejemplo, CTFontRef) no tienen un puente gratuito con sus homólogos de UIKit. Implementar su propio dibujo puede, a veces, ser más fácil, lo que garantizará la coincidencia de métricas.

  2. Core Text utiliza un sistema de coordenadas invertidas con respecto al sistema de dibujo iOS normal. Si obtiene resultados extravagantes, y especialmente si hace su propio dibujo, esto es algo que debe observar.

No es la tarea más fácil del mundo, pero lejos de ser imposible. ¡Buena suerte!

+0

En realidad, lo que me gustaría evitar es dibujar el texto, ya que parece ser una sobrecarga teniendo en cuenta la necesidad inicial. Consideraré las teclas-funciones de CoreText que usted dio, ¡gracias! – AgentCorleone

2

Aunque esta es una vieja pregunta, pero pensé que esto podría ser de alguna ayuda.

Desde el aprendizaje de texto básico era enorme, he optado por GLTapDemo by German Laullon

Con algunos cambios, esto funciona muy bien para la detección de la palabra tocado UILabel.

+1

Probé la solución VSWordDetector y esta, y encontré esta para trabajar de manera más efectiva para mi caso de uso. –

5

Después de buscar un poco, he escrito un código para esto. El código funcionará para UITextView y UILabel.
Simplemente descargue VSWordDetector.zip luego descomprímalo y arrastre & y coloque la carpeta VSWordDetector en su proyecto.
Hay dos archivos VSWordDetector.h y VSWordDetector.m
#import VSWordDetector.h en su clase ViewController.

@property (strong, nonatomic) VSWordDetector *wordDetector; 

Nota: Hacer su propiedad, no lo tome como a nivel local.

Ahora ya está listo para usted, basta con añadir en textViews o Labels

-(void)viewDidLoad 
{ 
    self.wordDetector = [[VSWordDetector alloc] initWithDelegate:self]; 
    [self.wordDetector addOnView:textView]; 
    [self.wordDetector addOnView:label]; 
} 

-(void)wordDetector:(VSWordDetector *)wordDetector detectWord:(NSString *)word 
{ 
    NSLog(@"Detected Word: %@", word); 
} 

Este delegado método se llama cuando se pulse sobre la etiqueta conectada o Textview.

EDIT: para VSWordDetector.

EDICION SUGERIDA: Si no desea descargar el código de ejemplo, aquí está el código para ambos archivos. Por favor, consulte este archivo esencial VSWordDetector.

+0

hola. Intenté usar tu código, pero no se detectó. Seguí los pasos que he dado, ¿puede decirme por favor dónde estoy yendo mal? –

+1

@NijilNair Lo siento pero no puedo decir dónde estás haciendo mal. Así que hice una muestra por favor vea Editar parte de mi respuesta. – TheTiger

+0

No me divierto mucho con el código comprimido. Agregue las partes relevantes de 'VSWordDetector' aquí o pegue el código en github. – Sulthan

Cuestiones relacionadas