I know the TextView
is embedded in a ScrollView
. And if there is a fairly long String
(Which contains no \"\\n\"
)<
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:
Reference: https://www.ralfebert.de/ios-examples/auto-layout/uiscrollview-storyboard/
[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.
UIScrollView
. Reference:- DualScrollTextViewI 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]
@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.)