0

Normally, changing the font of a UITextView is done like this:

textView.font = .systemFont(ofSize: 20)

This is fine if done before the text is loaded or right at the start of a long scrollable text view. However, if the font size is changed in the middle or end of a long text view, when scrolled to top, the text view leaves a huge chunk of empty space and forces an unpleasant resize.

Is there a way to allow a smooth change? How did Apple do it in its Books app?

enter image description here

Full code to reproduce this behavior:

import UIKit

class ViewController: UIViewController {
    var textView: UITextView!
    
    @objc func handleChange() {
        print("Clicked!")
        textView.font = .systemFont(ofSize: 20)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textView = UITextView()
        self.title = "TextView"
        let change = UIBarButtonItem(title: "change", style: .plain, target: self, action: #selector(handleChange))
        
        self.navigationItem.rightBarButtonItem = change
        
        textView.font = .systemFont(ofSize: 40)
        textView.frame = view.bounds
        view.addSubview(textView)
        textView.backgroundColor = .red
    }
}
TylerP
  • 9,600
  • 4
  • 39
  • 43
yaozhang
  • 69
  • 7

1 Answers1

0

"Abstract questions" can be very difficult to answer.

It seems unusual to do what you've shown -- changing the font for an entire text view in that way.

If you describe what your actual goal is, you may find that you're headed down the wrong path to begin with.

However, to avoid the specific issue you are running into with this code, you can "force" the text view to update its text layout:

@objc func handleChange() {
    print("Clicked!")
    textView.font = .systemFont(ofSize: 20)
    // tell the text view's layout manager to update
    textView.layoutManager.ensureLayout(for: textView.textContainer)
}
DonMag
  • 69,424
  • 5
  • 50
  • 86
  • My goal is to have the user adjust the font of the text displayed with that button directly. What are the better ways to do this? – yaozhang Nov 13 '22 at 17:57
  • Other people also mentioned this is not the correct way, but searching through SO, all other questions about UITextView font size are answered by ".font" attributes. Even this post with 30 upvotes said so. https://stackoverflow.com/questions/28742018/swift-increase-font-size-of-the-uitextview-how?rq=1 – yaozhang Nov 13 '22 at 18:04
  • @yaozhang - I think, in general, changing font size in a text view is discussed in terms of "rich-editing" ... that is, *"I want to make a word in the middle of a sentence bold/red/larger/smaller/etc."* Your question mentions: *"How did Apple do it in its Books app"* -- are you trying to develop a "reader" feature? Or a text-editor? – DonMag Nov 13 '22 at 18:27
  • I see. The functionality I ultimately want to achieve is a "reader" and not "editor". Currently, I simply replace the textview's attributedText property directly for font style changes, such as from a serif to sans-serif font with same font size, and this method works without any issues. It's only when I tinker with the font size the layout issue appears. The reader doesn't need to change specific font size, but only for the whole page. – yaozhang Nov 13 '22 at 18:32
  • 1
    @yaozhang - OK, you've fallen into the trap of "I think I should use this UI component" --- you almost certainly do ***NOT*** want to use a `UITextView` for a "reader," because you'll want the text to "flow from page to page," changing the amount that can fit on a page based on font / size. Take a look at this: [Core Text Tutorial for iOS: Making a Magazine App](https://www.kodeco.com/578-core-text-tutorial-for-ios-making-a-magazine-app) – DonMag Nov 13 '22 at 19:41