2013-11-15 4 views
11

Provo a rilevare quando il carrello si sposta su una nuova riga in UITextView. Posso rilevare che in confronto larghezza totale dopo con larghezza UITextView:Rileva momento quando newline viene avviato in UITextView

CGSize size = [textView.text sizeWithAttributes:textView.typingAttributes]; 
if(size.width > textView.bounds.size.width) 
     NSLog (@"New line"); 

Ma dose non funzionerà modo corretto perché -sizeWithAttributes:textView restituisce solo la larghezza di lettere senza larghezza del rientro. Aiutare per favore a risolvere questo.

+0

E 'questo lo standard 'UITextView' si sta utilizzando, o una versione sottoclasse? – n00bProgrammer

+0

È standard uno – mriddi

risposta

24

Ecco come lo farei:

  • Prendi il UITextPosition dell'ultimo carattere.
  • Chiama caretRectForPosition sul tuo UITextView.
  • Creare una variabile CGRect e memorizzare inizialmente CGRectZero in esso.
  • Nel metodo textViewDidChange:, chiamare caretRectForPosition: passando il UITextPosition.
  • Confrontarlo con il valore corrente memorizzato nella variabile CGRect. Se la nuova origine y di caretRect è maggiore della precedente, significa che è stata raggiunta una nuova linea.

codice di esempio:

CGRect previousRect = CGRectZero; 
- (void)textViewDidChange:(UITextView *)textView{ 

    UITextPosition* pos = yourTextView.endOfDocument;//explore others like beginningOfDocument if you want to customize the behaviour 
    CGRect currentRect = [yourTextView caretRectForPosition:pos]; 

    if (currentRect.origin.y > previousRect.origin.y){ 
      //new line reached, write your code 
     } 
    previousRect = currentRect; 

} 

Inoltre, si dovrebbe leggere la documentazione di riferimento UITextInput protocollo here. È magico, ti sto dicendo.

Fatemi sapere se avete altri problemi con questo.

+0

@mriddi. Ti ho dato una struttura scheletrica. Dovrai * aggiungere * per aggiungere le condizioni secondo le tue necessità. Ad esempio, modifica del codice nel mezzo del testo o sostituzione di parole o caratteri. – n00bProgrammer

+0

è brillante – mriddi

+0

Ci sono casi in cui questo non funzionerà. Cosa succede quando l'utente incolla nel testo e la posizione del cursore viene spostata nel processo? – rmaddy

0

È necessario ottenere l'altezza del testo, non la larghezza. Utilizzare sizeWithFont:constrainedToSize:lineBreakMode: (se è necessario supportare iOS 6 o versioni precedenti) o utilizzare boundingRectWithSize:options:attributes:context: se supporti solo iOS 7.

+0

Solo IOS7. Maggiori dettagli sull'utilizzo del secondo – mriddi

+0

Guarda i documenti. È simile al metodo 'sizeWithAttributes:' che stavi usando. Hai solo bisogno di passare in una taglia. Passa in una dimensione con la larghezza desiderata e un'altezza davvero grande. Le dimensioni restituite saranno le stesse ma con l'altezza necessaria per adattarsi al testo nella larghezza. – rmaddy

4

È possibile utilizzare l'UITextViewDelegate

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText: (NSString *)text 
{ 
    BOOL newLine = [text isEqualToString:@"\n"]; 
    if(newLine) 
    { 
      NSLog(@"User started a new line"); 
    } 
    return YES; 
} 
+0

Questa dovrebbe essere la risposta accettata. È molto elegante. L'attuale risposta accettata è molto hacky. –

6

Per uso Swift questo

previousRect = CGRectZero 

func textViewDidChange(textView: UITextView) { 

     var pos = textView.endOfDocument 
     var currentRect = textView.caretRectForPosition(pos) 
     if(currentRect.origin.y > previousRect?.origin.y){ 
      //new line reached, write your code 
     } 
     previousRect = currentRect 

    } 
2

Swift 3

La risposta accettata e la versione rapida funziona bene, ma qui è uno Swift Versione 3 per le persone pigre là fuori.

class CustomViewController: UIViewController, UITextViewDelegate { 

    let textView = UITextView(frame: .zero) 
    var previousRect = CGRect.zero 

    override func viewDidLoad(){ 
     textView.frame = CGRect(
      x: 20, 
      y: 0, 
      width: view.frame.width, 
      height: 50 
     ) 
     textView.delegate = self 
     view.addSubview(textView) 
    } 

    func textViewDidChange(_ textView: UITextView) { 
     let pos = textView.endOfDocument 
     let currentRect = textView.caretRect(for: pos) 
     if previousRect != CGRect.zero { 
      if currentRect.origin.y > previousRect.origin.y { 
       print("new line") 
      } 
     } 
     previousRect = currentRect 
    } 
} 
0

risposta @ n00bProgrammer in Swift-4 con più preciso rilevamento rottura linea.

@ n00bProgrammer risposta è perfetta tranne una cosa reagisce in modo diverso quando l'utente inizia a digitare in una prima linea, si presenta che Started New Line troppo.
Superare problema, ecco il codice raffinata

var previousRect = CGRect.zero 
    func textViewDidChange(_ textView: UITextView) { 
     let pos = textView.endOfDocument 
     let currentRect = textView.caretRect(for: pos) 
     self.previousRect = self.previousRect.origin.y == 0.0 ? currentRect : previousRect 
     if(currentRect.origin.y > previousRect.origin.y){ 
      //new line reached, write your code 
      print("Started New Line") 
     } 
     previousRect = currentRect 
    }