2012-01-10 14 views
5

Quello che mi piacerebbe fare è creare un componente text-container che sia in grado di indicare qual è la parola più vicina quando c'è un tocco su di essa (cioè la parola "dietro" "il punto toccato).Passare la parola in UILabel/UITextView

Per prima cosa, ho creato una sottoclasse UILabel e ho annullato il touchesEnded: withEvent: metodo per determinare il CGPoint toccato. Ho anche scritto un metodo che calcola il corrispondente "frame" (CGRect) di ogni parola del testo usando sizeWithFont: forWidth: lineBreakMode :. Con il CGPoint toccato e questo frame, posso determinare quale parola viene effettivamente toccata. Ma il metodo che calcola il frame funziona solo con testo a linea singola.

Così ora ho bisogno di sapere quale parte del testo è su una determinata linea (cioè come il testo è stato diviso), in modo da poter calcolare il margine sinistro e il margine superiore corretti di ogni parola.

Qualche idea su come ottenerlo? O forse hai una soluzione più semplice per raggiungere questo obiettivo? This post was unfortunately not very helpful... ...

risposta

9

(C'è un collegamento a un progetto di codice di esempio in tuo post collegato che contiene alcuni esempi di codice utile, ma mi illustrerà il processo per voi anche qui.)

In breve, avremo bisogno di usare Core Text, che è l'avanzato framework di gestione testi basato su C di Apple che supporta tutti i sofisticati layout di testo in iOS e OS X.

Il codice completo sarà in qualche modo coinvolto, ma i metodi chiave che sei intenzione di voler vedere sono:

CTFramesetterCreateWithAttributedString() - utilizzare questo, in congi unzione con una stringa NSA attribuita ottenuta dal testo della tua etichetta - per creare il frameset

CTFramesetterCreateFrame() - usa questo per ottenere un CTFrameRef per il tuo testo dal frameest sopra. Dovrai creare un CGPathRef usando i limiti dell'etichetta per farlo.

CTFrameGetLines(), CTFrameGetLineOrigins() - utilizzare questi per ottenere CTLineRefs corrispondenti alle linee di composizione, e le coordinate delle origini delle linee, rispettivamente, allora utilizzare CTLineGetStringIndexForPosition() per trovare l'indice di carattere in una posizione tocco.

È quindi possibile utilizzare questo indice di caratteri (nel riquadro di riferimento della linea) per lavorare all'indietro e trovare il carattere/parola/ecc. Effettivi all'interno della stringa completa.

Non dimenticare che le questioni sono complicate da un paio di problemi:

  1. Se si utilizza di UILabel nativo disegno che si dovrà prendere cura per abbinare perfettamente le metriche di composizione, che può essere ingombrante poiché la maggior parte gli oggetti (ad es. CTFontRef) non sono pedonabili con le loro controparti UIKit. A volte, implementare il tuo disegno potrebbe essere più semplice, il che garantirà la corrispondenza delle metriche.

  2. Core Text utilizza un sistema di coordinate invertito rispetto al normale sistema di disegno iOS. Se stai ottenendo risultati stravaganti, e specialmente se fai il tuo disegno, questo è qualcosa da dare un'occhiata.

Non è il compito più semplice del mondo, ma non impossibile. In bocca al lupo!

+0

In realtà, disegnare il testo da solo è ciò che vorrei evitare poiché sembra essere un po 'eccessivo considerando la necessità iniziale. Prenderò in considerazione le funzioni dei tasti CoreText che hai dato, grazie! – AgentCorleone

2

Anche se questa è una vecchia domanda, ma ho pensato che questo potrebbe essere di qualche aiuto.

Poiché l'apprendimento testo principale era enorme, ho optato per GLTapDemo by German Laullon

Con alcuni cambiamenti, questa grande opera per la rilevazione di parola toccato UILabel.

+1

Ho provato sia la soluzione VSWordDetector che questa, e ho trovato che questa funzionava in modo più efficace per il mio caso d'uso. –

5

Dopo aver cercato un po 'ho scritto un codice per questo. Il codice funzionerà per UITextView e UILabel.
Basta scaricare VSWordDetector.zip quindi decomprimerlo e trascinare & rilasciare la cartella VSWordDetector nel progetto.
Ci sono due file VSWordDetector.h e VSWordDetector.m
#import VSWordDetector.h nella classe ViewController.

@property (strong, nonatomic) VSWordDetector *wordDetector; 

Nota: Fai la sua proprietà non prendere come a livello locale.

Ora il suo pronto per voi, Basta aggiungere su 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); 
} 

Questo delegato metodo sarà chiamata quando si tocca sull'etichetta collegato o textView.

EDIT: per VSWordDetector.

MODIFICA CONSIGLIATA: Se non si desidera scaricare il codice di esempio, qui è il codice per entrambi i file. Si prega di consultare questo file Gist VSWordDetector.

+0

ciao. Ho provato a usare il tuo codice, ma il rubinetto non viene rilevato. Ho seguito i passi che hai dato, puoi dirmi dove sto andando storto? –

+1

@NijilNair Scusa ma non posso dire dove stai sbagliando. Quindi ho fatto un esempio per favore vedi Modifica parte della mia risposta. – TheTiger

+0

Non sono un grande divertimento per il codice zippato. Aggiungi qui le parti rilevanti di "VSWordDetector" o incolla il codice su github. – Sulthan

Problemi correlati