2017-12-04 5 views
2

私はUITextViewに常に同じ固定高さにキャレットを保持するようにしようとしています(例えば、画面の1/4に)。タイプライターエフェクトを作成するには、UITextViewでキャレットの位置をロックする方法はありますか?

私は古いタイプライターと同じように動作するはずです。ユーザーがenter(またはend of line)を押すと、テキストは1行上にスクロールし、キャレットは同じyの位置に留まり、新しい行の先頭にジャンプします。

私はそれをそうしようとしていましたが、予期しない動作をしました。キャレットは時々ランダムにジャンプし、スクロールが表示され、スクロールしてからscrollRectToVisibleでスクロールします。それ。

どうすればこのような効果を得ることができますか?同様の機能を備えたライブラリやポッドも高く評価されます。ここで

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) 
    } 
} 
+1

私は意図した効果を理解するのに苦労しています。あなたのコードでは、画面の測定をたくさん行っているようです。それはいいですが、あなたはどのような進歩を遂げましたか?あなたが持っているコードはどうなっていますか?何が起こると予想されていますか、そして実際には何が起こっていますか? –

+0

'UITextView'を' UIScrollView'にラップして実装します。 – kelin

+0

@kelin UIScrollViewでラップする必要はありません.UITextFieldクラスの定義を確認すると、実際には既にUIScrollViewのサブクラスが表示されます。 –

答えて

1

私はどうなるのかです:

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) 
} 

}

付:まずviewDid負荷に

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

をこれらの設定

そして、この拡張機能を追加これはあなたがtypewriを得るどこにでもジャンプすることなく、効果を発揮します。 didendEditingメソッドは、元の0,0にスクロールするためだけにあります。あなたがそれを単に削除する必要がない場合。

+0

それはほとんど私が探していたものですが、私はいくつかの修正を加えなければなりませんでした。キャレットの 'yPosition'だけをロックしたかったです(テキストは右から左に移動すべきではありません) - 簡単に修正できました(' xPos'を0 )また、テキストを手動でスクロールできるようにしたいので、 'textView.isScrollEnabled'をオンにしました。 'trackCaret'を' textChangeTextIn'から 'textViewDidChangeSelection'に移動しました。それは今、ちょっとうまくいくが、まだいくつかの不具合がある。例えば、ダブルスペースをタップしてテキストビューを変更すると、ドットスクロールが何らかの理由で画面から消えてしまう。 – szooky

+0

私はtextviewのオートコレクトをオフにすることができると思う。ユーザーが入力するのではなくテキストをペーストすると、奇妙なことも起こる可能性があります。あなたがどのように対処したいかを決めるのに必要なこれらの小さなもの。 –

関連する問題