2013-11-15 14 views
11

Próbuję wykryć, kiedy karetka przechodzi do nowej linii w UITextView. Mogę go wykryć przez porównania całkowitej szerokości późniejszym o szerokości UITextView:Wykryj moment, w którym zaczyna się nowa linia w UITextView

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

Ale dawki nie działają właściwy sposób, ponieważ -sizeWithAttributes:textView zwraca tylko szerokość liter bez szerokości wcięcia. Pomóż proszę rozwiązać ten problem.

+0

Jest to standardowe 'UITextView' używasz lub podklasy wersja? – n00bProgrammer

+0

Jest to standardowy jeden tylko – mriddi

Odpowiedz

24

ten sposób byłoby to zrobić:

  • Pobierz UITextPosition ostatniego znaku.
  • Zadzwoń pod caretRectForPosition pod numer UITextView.
  • Utwórz zmienną CGRect i początkowo zapisz w niej CGRectZero.
  • W swojej metodziezadzwoń pod numer caretRectForPosition:, przekazując UITextPosition.
  • Porównaj z bieżącą wartością przechowywaną w zmiennej CGRect. Jeśli nowe pochodzenie y caretRect jest większe niż ostatnie, oznacza to, że osiągnięto nową linię.

Przykładowy kod:

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; 

} 

Ponadto, należy zapoznać się z dokumentacją odniesienia protokołu UITextInputhere. To magiczne, mówię ci.

Daj mi znać, jeśli masz z tym jakieś inne problemy.

+0

@mriddi. Dałem ci strukturę szkieletu. Będziesz * mieć *, aby dodać warunki zgodnie ze swoją potrzebą. Na przykład, edytując kod w środku tekstu lub zastępując słowa lub znaki. – n00bProgrammer

+0

jest genialny – mriddi

+0

Istnieją przypadki, w których to nie zadziała. A co się stanie, gdy użytkownik wklei tekst, a pozycja karetki zostanie przeniesiona? – rmaddy

0

Musisz uzyskać wysokość tekstu, a nie szerokość. Użyj albo sizeWithFont:constrainedToSize:lineBreakMode: (jeśli trzeba wspierać iOS 6 lub wcześniej) lub użyć boundingRectWithSize:options:attributes:context: jeśli tylko wspierać iOS 7.

+0

Tylko IOS7. Plz więcej szczegółów na temat korzystania z drugiego – mriddi

+0

Spójrz na dokumenty. Jest to podobne do metody 'sizeWithAttributes:', której używasz. Po prostu musisz podać swój rozmiar. Podaj rozmiar o pożądanej szerokości i naprawdę dużej wysokości. Zwrócony rozmiar będzie taki sam, ale z wymaganą wysokością, aby dopasować tekst do szerokości. – rmaddy

4

Można użyć 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

To powinna być zaakceptowana odpowiedź. Jest najbardziej elegancki. Obecna zaakceptowana odpowiedź jest bardzo hackowata. –

6

do szybkiego wykorzystania tego

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

Zaakceptowanych odpowiedź i szybka wersja działa dobrze, ale tutaj jest Swift 3 wersja dla leniwych ludzi.

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

odpowiedź @ n00bProgrammer w Swift-4 z bardziej precyzyjne wykrywanie przerwy linii.

@ n00bProgrammer odpowiedź jest idealne, z wyjątkiem jednej rzeczy reaguje inaczej, gdy użytkownik zaczyna wpisywać się w pierwszej linii, stwarzał Started New Line też.
Przezwyciężenie problemu, oto kod wyrafinowany

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 
    }