How would I set the font size of text in a UITextView such that it fills the entire UITextView? I\'d like the user to type in their text, then have the text fill the entire
I have converted Matt Frear's answer to Swift 4.1 as extension for UITextView:
extension UITextView {
func updateTextFont() {
if (self.text.isEmpty || self.bounds.size.equalTo(CGSize.zero)) {
return;
}
let textViewSize = self.frame.size;
let fixedWidth = textViewSize.width;
let expectSize = self.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT)))
var expectFont = self.font
if (expectSize.height > textViewSize.height) {
while (self.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT))).height > textViewSize.height) {
expectFont = self.font!.withSize(self.font!.pointSize - 1)
self.font = expectFont
}
}
else {
while (self.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT))).height < textViewSize.height) {
expectFont = self.font
self.font = self.font!.withSize(self.font!.pointSize + 1)
}
self.font = expectFont
}
}
}
Similar approach to Arie Litovsky's answer but without sub-classing (or use of a category) and not using contentSize
which didn't return the correct height of the rendered text for me. Tested on iOS 7:
while (((CGSize) [_textView sizeThatFits:_textView.frame.size]).height > _textView.frame.size.height) {
_textView.font = [_textView.font fontWithSize:_textView.font.pointSize-1];
}
The approach is to keep reducing the font size until the text just fits inside the frame of the text view.
If you were going to use this in production you would still need to:
for swift 3
func updateTextFont(textView: UITextView) {
if (textView.text.isEmpty || textView.bounds.size.equalTo(CGSize.zero)) {
return
}
let textViewSize = textView.frame.size
let fixedWidth = textViewSize.width
let expectSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT)))
var expectFont = textView.font;
if (expectSize.height > textViewSize.height) {
while (textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT))).height > textViewSize.height) {
expectFont = textView.font!.withSize(textView.font!.pointSize - 1)
textView.font = expectFont
}
}
else {
while (textView.sizeThatFits(CGSize(width: fixedWidth,height: CGFloat(MAXFLOAT))).height < textViewSize.height) {
expectFont = textView.font
textView.font = textView.font!.withSize(textView.font!.pointSize + 1)
}
textView.font = expectFont
}
}
I have converted dementiazz's answer to Swift:
func updateTextFont() {
if (textView.text.isEmpty || CGSizeEqualToSize(textView.bounds.size, CGSizeZero)) {
return;
}
let textViewSize = textView.frame.size;
let fixedWidth = textViewSize.width;
let expectSize = textView.sizeThatFits(CGSizeMake(fixedWidth, CGFloat(MAXFLOAT)));
var expectFont = textView.font;
if (expectSize.height > textViewSize.height) {
while (textView.sizeThatFits(CGSizeMake(fixedWidth, CGFloat(MAXFLOAT))).height > textViewSize.height) {
expectFont = textView.font!.fontWithSize(textView.font!.pointSize - 1)
textView.font = expectFont
}
}
else {
while (textView.sizeThatFits(CGSizeMake(fixedWidth, CGFloat(MAXFLOAT))).height < textViewSize.height) {
expectFont = textView.font;
textView.font = textView.font!.fontWithSize(textView.font!.pointSize + 1)
}
textView.font = expectFont;
}
}
Swift 3.0+ Update:
func updateTextFont() {
if (textView.text.isEmpty || textView.bounds.size.equalTo(CGSize.zero)) {
return;
}
let textViewSize = textView.frame.size;
let fixedWidth = textViewSize.width;
let expectSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT)));
var expectFont = textView.font;
if (expectSize.height > textViewSize.height) {
while (textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT))).height > textViewSize.height) {
expectFont = textView.font!.withSize(textView.font!.pointSize - 1)
textView.font = expectFont
}
}
else {
while (textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT))).height < textViewSize.height) {
expectFont = textView.font;
textView.font = textView.font!.withSize(textView.font!.pointSize + 1)
}
textView.font = expectFont;
}
}
Try this, it's a lot simpler:
while (self.contentSize.height > self.frame.size.height)
{
self.font = [self.font fontWithSize:self.font.pointSize -1];
}
Hope that's clearer:
extension UITextView {
@objc public func fitText() {
fitText(into: frame.size)
}
@objc public func fitText(into originalSize: CGSize) {
let originalWidth = originalSize.width
let expectedSize = sizeThatFits(CGSize(width: originalWidth, height: CGFloat(MAXFLOAT)))
if expectedSize.height > originalSize.height {
while let font = self.font, sizeThatFits(CGSize(width: originalWidth, height: CGFloat(MAXFLOAT))).height > originalSize.height {
self.font = font.withSize(font.pointSize - 1)
}
} else {
var previousFont = self.font
while let font = self.font, sizeThatFits(CGSize(width: originalWidth, height: CGFloat(MAXFLOAT))).height < originalSize.height {
previousFont = font
self.font = font.withSize(font.pointSize + 1)
}
self.font = previousFont
}
}
}