2 years ago
#57563

Sweeper
How do I prevent the scroll view from scrolling to the start when editing a big text view in it?
I am trying to make an editable, multiline, UITextView
that can horizontally scroll. From multiple answers I found (1, 2, 3), it seems like I should put the UITextView
into a UIScrollView
, so I did exactly that. However, the editing experience turned out to be awful.
Here is an MCVE:
class MyViewController: UIViewController {
// connect this outlet to a scroll view that covers the whole screen
@IBOutlet var scrollView: UIScrollView!
var textView: UITextView!
override func viewDidLoad() {
setupTextView()
scrollView.addSubview(textView)
}
let font = UIFont.monospacedSystemFont(ofSize: 23, weight: .regular)
func setupTextView() {
// My text view is going to contain a maximum of 80x25 characters, so here
// I am calculating how much space that is going to take up
let line = String(repeating: "a", count: 81)
let fullText = Array(repeating: line, count: 26).joined(separator: "\n")
let unroundedSize = (fullText as NSString).size(withAttributes: [
.font: font
])
let size = CGSize(width: ceil(unroundedSize.width), height: ceil(unroundedSize.height))
textView = UITextView(frame: CGRect(origin: .zero, size: size))
scrollView.contentSize = size
textView.spellCheckingType = .no
textView.dataDetectorTypes = []
textView.font = font
// dummy text
textView.text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et finibus turpis.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et finibus turpis.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et finibus turpis.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras et finibus turpis.
"""
// the text view do not need to scroll. All the scrolling is done
// by the scroll view
textView.isScrollEnabled = false
}
}
To see how awful the editing experience is, put the cursor at the end of the text, then try deleting some of the text at the end of the string by holding down the delete key. The scroll view "flickers" between where the cursor is, and the far left of the text view, i.e. these two states:
I tried to scroll to the cursor whenever the cursor moved by doing:
func textViewDidChangeSelection(_ textView: UITextView) {
guard let range = textView.selectedTextRange else { return }
let rect = textView.caretRect(for: range.end)
guard !CGRect(origin: scrollView.contentOffset, size: scrollView.visibleSize).intersects(rect) else { return }
scrollView.scrollRectToVisible(rect, animated: true)
}
but that didn't improve the awful behaviour of the delete key at all.
How can I prevent the scroll view from scrolling to the start?
ios
swift
uiscrollview
uitextview
0 Answers
Your Answer