2 votes

Comment verrouiller la position du curseur dans UITextView pour créer un effet de machine à écrire ?

J'essaie de forcer UITextView pour garder le signe d'insertion toujours à la même hauteur fixe, par exemple dans le quart de l'écran.

Je devrais me comporter comme les anciennes machines à écrire - lorsque l'utilisateur appuie sur la touche Entrée (ou atteint la fin de la ligne), le texte devrait défiler d'une ligne vers le haut et le curseur devrait rester dans la même position y et sauter au début de la nouvelle ligne.

J'ai essayé de le faire comme ça, mais il se comporte de manière inattendue, le caret saute parfois de manière aléatoire et le défilement est visible, il se fait défiler vers le bas et ensuite je le fais défiler vers le haut avec scrollRectToVisible cela ne semble pas être la manière idéale de le faire.

Comment puis-je obtenir un tel effet ? Toute bibliothèque ou pod ayant une fonctionnalité similaire serait également très appréciée.

func setScrollToMiddle() {
    if let selectedRange = textView.selectedTextRange {

        let caretRect = textView.caretRect(for: selectedRange.start)            
        let middleOfCaretHeight = caretRect.origin.y + (caretRect.height / 2)
        let screenHeight = UIScreen.main.bounds.height
        guard let kbSize = self.keyboardSize else { return }
        let keyboardHeight = kbSize.height
        let visibleTextAreaHeight = screenHeight - keyboardHeight - topMenuView.frame.height
        let finalRectY = middleOfCaretHeight - topMenuView.frame.height - (visibleTextAreaHeight / 2)

        let finalRect = CGRect(x: 0.0, y: finalRectY, width: textView.frame.width, height: visibleTextAreaHeight)

        textView.scrollRectToVisible(finalRect, animated: false)
    }
}

3voto

Andreas M. Points 11

Voici ce que je ferais :

D'abord mettre en place ces dans la charge viewDid

override func viewDidLoad() {
    super.viewDidLoad()
    textView.delegate = self
    textView.isEditable = true
    textView.isScrollEnabled = false
}

Ajoutez ensuite cette extension :

extension ViewController: UITextViewDelegate {
func trackCaret(_ textView:UITextView){
    if let selectedRange = textView.selectedTextRange {
        let caretRect = textView.caretRect(for: selectedRange.start)
        let yPos = caretRect.origin.y - (textView.frame.height/2)
        let xPos = caretRect.origin.x - (textView.frame.width/2)
        textView.bounds.origin = CGPoint(x: xPos, y: yPos)
    }
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    trackCaret(textView)
    return true
}
func textViewDidBeginEditing(_ textView: UITextView) {
    trackCaret(textView)
}
func textViewDidEndEditing(_ textView: UITextView) {
    // If you don't need to move back to the original position you can leave this out
    //  textView.bounds.origin = CGPoint.zero
    //or if you want smooth animated scroll back then
    textView.scrollRectToVisible(CGRect(x:0,
                                        y:0,
                                        width: textView.bounds.width,
                                        height: textView.bounds.height),
                                 animated: true)
}

}

Vous obtenez ainsi l'effet machine à écrire sans sauter partout. La méthode didendEditing n'est là que pour revenir à l'origine 0,0. Si vous n'avez pas besoin de le faire, supprimez-la.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X