2016-04-16 14 views
0

Ich versuche zu erkennen, wenn der Benutzer einen bestimmten Punkt in einem Text erreicht: String in einem UITextView. Ich verwende scrollViewDidEndDragging, aber das Ergebnis ist nicht ideal. Wenn ich mit dem Scrollen fertig bin, muss ich noch weiter scrollen, damit es passiert. Wenn der Text nur 1 Seite lang ist, wird diese Methode auch nie aufgerufen. Gibt es einen besseren Weg zu wissen, wann die letzte Zeile (oder eine andere Zeile) auf dem Bildschirm sichtbar ist? DankeEnde von UITextView Text in Swift

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) { 
     let bottomEdge: CGFloat = textField.contentOffset.y + textField.frame.size.height 
     if (bottomEdge >= scrollView.contentSize.height) { 
      //do stuff 
     } 
    } 

Antwort

0

Hier ist eine naive Lösung ist, die die rect und Checks String wird, ob das rect sichtbar ist.

Der Hauptnachteil bei dieser Implementierung ist, dass es nur funktioniert, wenn Ihre Teilzeichenfolge eindeutig ist (weil sie nur das erste Vorkommen erfasst). Aber das sollte nicht zu schlecht sein, um es zu implementieren (vielleicht mit einem Array von Rezepten, die Sie überprüfen).

UITextView Helfer

Ich habe eine Erweiterung auf UITextView für Komfort geschaffen. Es bietet zwei Methoden: Eine für die Bestimmung der Rect eines Teilstrings und eine andere für die Überprüfung, ob dieser Rect sichtbar ist.

rectForText ist ziemlich ausführliche vor allem wegen der Umwandlung von Range<Index> in UITextRange, die schmerzhaften erwiesen als erwartet. Wenn jemand einen einfacheren Weg kennt, bitte teilen.

extension UITextView { 
    func rectForText(targetText: String) -> CGRect? { 
     if let range = text.rangeOfString(targetText) { 
      let beginning = beginningOfDocument 
      let startOffset = text.startIndex.distanceTo(range.startIndex) 
      if let start = positionFromPosition(beginning, offset: startOffset) { 
       let endOffset = text.startIndex.distanceTo(range.endIndex) - startOffset 
       if let end = positionFromPosition(start, offset: endOffset) { 
        if let textRange = textRangeFromPosition(start, toPosition: end) { 
         return firstRectForRange(textRange) 
        } 
       } 
      } 
     } 

     return nil 
    } 

    func isRectVisible(rect: CGRect?) -> Bool { 
     if let rect = rect { 
      return CGRectIntersectsRect(rect, bounds) 
     } 

     return false 
    } 
} 

Testcode

Endlich habe ich ein einfaches Testprojekt erstellt, die einen View-Controller mit einer einzigen Textansicht hat. Beachten Sie, dass bei der Anzeige der Ansicht die Sichtbarkeit überprüft wird und anschließend kontinuierlich, während die Bildlaufansicht gescrollt wird. Ich habe auch den Test rect gespeichert, um zu vermeiden, dass er bei jedem Scrollen neu berechnet wird. Aber wenn Sie Text dynamisch sind, müssen Sie dies neu berechnen.

+0

es ist das gleiche mit meiner Lösung ... – PoolHallJunkie

+0

@PoolHallJunkie Hey, du hast Recht, meine Antwort war nicht vollständig. Ich habe meine Antwort vollständig mit einer Lösung umgeschrieben, die ich jetzt getestet habe. Hoffentlich ist dies eine bessere Lösung. – nebs

Verwandte Themen