【发布时间】:2011-01-03 13:59:40
【问题描述】:
如何在 UITextView 中设置文本的字体大小以使其填充整个 UITextView?我希望用户输入他们的文本,然后让文本填充整个 UITextView。
感谢任何帮助!
【问题讨论】:
标签: iphone cocoa-touch uikit uitextview font-size
如何在 UITextView 中设置文本的字体大小以使其填充整个 UITextView?我希望用户输入他们的文本,然后让文本填充整个 UITextView。
感谢任何帮助!
【问题讨论】:
标签: iphone cocoa-touch uikit uitextview font-size
此属性仅在 UITextFields 上可用。要在 UITextView 中执行此操作,您必须不断观察文本并在更改时手动调整字体大小。
【讨论】:
这在 UITextView 的一个类别中应该可以解决问题。为什么需要 fudgefactor,请参阅 this post
#define kMaxFieldHeight 9999
-(BOOL)sizeFontToFit:(NSString*)aString minSize:(float)aMinFontSize maxSize:(float)aMaxFontSize
{
float fudgeFactor = 16.0;
float fontSize = aMaxFontSize;
self.font = [self.font fontWithSize:fontSize];
CGSize tallerSize = CGSizeMake(self.frame.size.width-fudgeFactor,kMaxFieldHeight);
CGSize stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
while (stringSize.height >= self.frame.size.height)
{
if (fontSize <= aMinFontSize) // it just won't fit
return NO;
fontSize -= 1.0;
self.font = [self.font fontWithSize:fontSize];
tallerSize = CGSizeMake(self.frame.size.width-fudgeFactor,kMaxFieldHeight);
stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
}
return YES;
}
【讨论】:
试试这个,简单多了:
while (self.contentSize.height > self.frame.size.height)
{
self.font = [self.font fontWithSize:self.font.pointSize -1];
[self layoutSubviews];//force .contentSize to update
}
【讨论】:
与 Arie Litovsky 的答案类似,但没有子分类(或使用类别),也没有使用 contentSize,它没有为我返回渲染文本的正确高度。在 iOS 7 上测试:
while (((CGSize) [_textView sizeThatFits:_textView.frame.size]).height > _textView.frame.size.height) {
_textView.font = [_textView.font fontWithSize:_textView.font.pointSize-1];
}
方法是不断减小字体大小,直到文本刚好适合文本视图的框架。
如果您要在生产中使用它,您仍然需要:
【讨论】:
这是我的示例代码。基本上,我检查期望大小以了解字体大小是否需要增加或减少。您需要将 UITextViewDelegate 添加到您的课程中以确保其正常工作
- (void)updateTextFont:(UITextView *)textView
{
// Only run if has text, otherwise it will make infinity loop
if (textView.text.length == 0 || CGSizeEqualToSize(textView.bounds.size, CGSizeZero)) return;
/*
- Update textView font size
If expectHeight > textViewHeight => descrease font size n point until it reach textViewHeight
If expectHeight < textViewHeight => inscrease font size n point until it reach textViewHeight
*/
CGSize textViewSize = textView.frame.size;
CGFloat fixedWidth = textViewSize.width;
CGSize expectSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
UIFont *expectFont = textView.font;
if (expectSize.height > textViewSize.height) {
while ([textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)].height > textViewSize.height) {
expectFont = [textView.font fontWithSize:(textView.font.pointSize-1)];
textView.font = expectFont;
}
} else {
while ([textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)].height < textViewSize.height) {
expectFont = textView.font;
textView.font = [textView.font fontWithSize:(textView.font.pointSize+1)];
}
textView.font = expectFont;
}
}
【讨论】:
expectFont 设置为textView's font... 然后将其设置回未修改的font?是为了防止文字大小的上下跳跃吗?
textView.font 不会改变(因为expectFont 实际上是原始的textView.font)。但是如果至少运行 1 次,expectFont 会发生变化,我们需要在完成循环后更新它。我可以制作一个标志来确定是否运行,但我没有。相反,我将它分组到最后一行 textView.font = expectFont
expectFont 中。然后你将textView 的字体增加一点,但是当while 循环退出时,你会看到textView 字体恢复到原来的样子......
textView.font,所以while条件为false(我是直接用textView计算条件的)。这意味着我设置的字体不正确,我必须回滚才能期待字体。
我已将dementiazz's answer 转换为 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+ 更新:
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;
}
}
【讨论】:
viewDidLayoutSubviews
@Arie Litovsky 代码的更新版本。这适用于 iOS7 及更高版本,并且可以上下拉伸字体大小以使文本适合。
- (void) stretchFontToFit:(UITextView*)textView
{
while( textView.contentSize.height < textView.frame.size.height )
{
textView.font = [textView.font fontWithSize:textView.font.pointSize +1];
[textView layoutIfNeeded];
}
while( textView.contentSize.height > textView.frame.size.height )
{
textView.font = [textView.font fontWithSize:textView.font.pointSize -1];
[textView layoutIfNeeded];
}
}
【讨论】:
在 viewDidLoad 中:
textView.textContainer.lineFragmentPadding = 0;
textView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0);
需要添加 UITextViewDelegate:
- (void)updateTextFont:(UITextView *)textView {
CGSize textViewSize = textView.frame.size;
CGSize sizeOfText = [textView.text sizeWithAttributes:@{NSFontAttributeName: textView.font}];
CGFloat fontOfWidth = floorf(textView.font.pointSize / sizeOfText.height * textViewSize.height);
CGFloat fontOfHeight = floorf(textView.font.pointSize / sizeOfText.width * textViewSize.width);
textView.font = [textView.font fontWithSize:MIN(fontOfHeight, fontOfWidth)];
}
【讨论】:
我已将痴呆症和马特弗雷尔的答案转换为 Swift 3:
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
}
}
【讨论】:
你可以通过使用轻松做到这一点
self.textview.font = self.textview.font = UIFont(name: self.textview.font!.fontName,
尺寸:self.textview.frame.size.height / 10)!
根据您的要求将 textview.frame.size.height 划分为某个常数..
【讨论】:
对于 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
}
}
【讨论】:
这是 Swift 4 的解决方案(基于Arie Litovsky 答案),您可以将此代码放入textViewDidChange(_ textView: UITextView) 委托方法中:
缩小字体:
while (textView.contentSize.height > textView.frame.size.height) {
guard let fontName = textView.font?.fontName, let fontSize = textView.font?.pointSize else {return}
if fontSize < 12 {
return
}
textView.font = UIFont(name: fontName, size: fontSize - 1)
textView.layoutIfNeeded()
}
并放大字体:
while (textView.contentSize.height < textView.frame.size.height) {
guard let fontName = textView.font?.fontName, let fontSize = textView.font?.pointSize else {return}
if fontSize > 15 {
return
}
textView.font = UIFont(name: fontName, size: fontSize + 1)
textView.layoutIfNeeded()
}
您可以更改fontSize < 12 和fontSize > 15 以满足您对最小和最大字体大小的需求。
【讨论】:
我已将 Matt Frear 的答案转换为 Swift 4.1 作为 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
}
}
}
【讨论】:
这里是dementiazz's 和Matt Frear's 对Swift 5 的回答的转换。将此函数放入viewDidLayoutSubviews,引用UITextView 的要动态调整大小的字体。
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;
}
}
【讨论】:
希望这更清楚:
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
}
}
}
【讨论】: