How to let TextView be able to scroll horizontally

前端 未结 4 1263
心在旅途
心在旅途 2020-12-31 12:38

I know the TextView is embedded in a ScrollView. And if there is a fairly long String(Which contains no \"\\n\")<

相关标签:
4条回答
  • 2020-12-31 12:55

    The accepted answer didn't work with AutoLayout so I'll share my approach:

    1. Add a UIScrollView with a UITextView inside it and pin all the edges for both of them

    2. Add width and height constraints for your UITextView (doesn't matter what you set them to)

    3. Create IBOutlets for the UITextView, the height constraint, and the width constraint

    4. Uncheck 'Scrolling Enabled' on the TextView

    5. When you update the text, calculate the bounding size of the text and update the height and width constraints with the bounding size

    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var textViewHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var textViewWidthConstraint: NSLayoutConstraint!
    
    let displayText = "Your text here."
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let maxSize = CGSize(width: 10000, height: 30000)
        let textRect = displayText.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font : self.textView.font!], context: nil)
    
        self.textView.text = displayText
        self.textViewHeightConstraint.constant = textRect.height
        self.textViewWidthConstraint.constant = textRect.width
    }
    

    UPDATE: I discovered that this approach uses a lot of memory for large amounts of text (I was seeing over 1GB used). Here's how I reduced the memory impact from 1GB to 100MB:

    1. Set the edge constraints just like step 1 above.

    2. Add a width constraint to the TextView for the scrollable content width (I used 2000 but you can adjust it to your liking, the wider you go the more memory you'll use though).

    3. Add a constraint to make the TextView and ScrollView have equal heights

    That's it! The scrollable width will be constant and once you set the text for the TextView the scrollable height will automatically adjust.

    Note: Some caveats of this approach:

    • The scrollable width will always be the width you set but you can use a hybrid approach with the first solution if you want to make it sized based on the text
    • You can't see the vertical scroll bar (unless you're scrolled all the way to the right) but it's possible to get it back by adjusting the scroll bar inset of the TextView.

    Reference: https://www.ralfebert.de/ios-examples/auto-layout/uiscrollview-storyboard/

    0 讨论(0)
  • 2020-12-31 13:13
    1. [myTextView setContentSize:CGSizeMake(width, myTextView.frame.size.height)];

    The width of the content extends past the width of the textView's frame or else it won't scroll.

    1. Turn off all the scroll options on the UITextView, then embed it in another UIScrollView. Reference:- DualScrollTextView
    0 讨论(0)
  • 2020-12-31 13:15

    I figure out how to do this with many helps of you guys :D, thanks, and here we go!

    1. So, firstly, We need a longlonglong String, right?

    let displayStr = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 "
    

    2. Assume we have a UIScrollView which is linked by @IBOutlet or got by calling the .viewWithTag(xxx) .We will let it be named as scroll :

    3. It's time to get the size of our string, here is a key function we'll use it:

    Oh! I almost forget to define what kind of Font( this's a crucial parameter ) we will use, and What is the max-size of our string's size

    let maxSize = CGSizeMake(9999, 9999)
    let font = UIFont(name: "Menlo", size: 16)!
    //key function is coming!!!
    let strSize = (displayStr as NSString).boundingRectWithSize(maxSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName : font], context: nil)
    

    4. OK, now we can put the string into a textView, you need to programmatically create a new UITextView, so that we can define the frame which is identical to the string's size(Oh, maybe a little bigger :D) :

    let frame = CGRectMake(0, 0, size.width+50, size.height+10)
    let textView = UITextView(frame: frame)
    textView.editable = false
    textView.scrollEnabled = false//let textView becomes unScrollable
    textView.font = font
    textView.text = displayStr
    

    5. Back to our scroll, we will set its contentSize:

    scroll.contentSize = CGSizeMake(size.width, size.height)

    6. Finally, addSubview: scroll.addSubview(textView)

    You can see, textView is embed in a scrollView, which allow it to scroll with 2 directions.

    B.T.W. My implement is just a demo for static String. if you want user to use a textView which will not line wrap if he doesn't input any "\n", you may need dynamically calculate the string size. :D

    [I hope this will help]

    0 讨论(0)
  • 2020-12-31 13:16
    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textView: UITextView!
    
    var yourText: String = "Whatever your text is going to be." 
    
    override func viewDidLayoutSubviews() {
    
        super.viewDidLayoutSubviews()
        self.scrollView.layoutIfNeeded()
        self.scrollView.contentSize = self.textView.bounds.size
    
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
    textView.text = yourText
    
        textView.sizeThatFits(CGSizeMake(textView.frame.size.width, 80)) //height to equal the actual size of your text view.
    
    }
    

    I think this should plug and play, but I know for sure that textView.sizeThatFits works. You have to make sure that you constrain your text view to it's parent scrollview for it to work. (Leading, Trailing, Top, Bottom and the Height.)

    0 讨论(0)
提交回复
热议问题