我需要将用户输入的大型多行UITextView
的文本移动到较小的(但仍然是多行的)UITextView
*中。如果用户输入的文本多于在较小视图中显示的文本,我想截断文本,使其适合所有可见的(截断的)文本。 (大的UITextView
和小的NSString
都不应该滚动。)
最好的方法是什么?
我可以使用循环,每次都用字符缩短字符串,然后使用sizeWithFont: constrainedToSize: lineBreakMode:
的{{1}}找出这个较短字符串所需的高度,然后将其与高度我可以在我较小的UITextView
中使用,当字符串适合时结束循环 - 但这看起来很慢而且很尴尬。必须有更好的方法。
我想告诉目的地UITextView
截断它的displayText成员,因为它在屏幕上显示它,但我找不到办法做到这一点。
*更多关于此的背景,来自我在下面做出的评论:
我有一个风景应用程序。我根据用户选择的照片更改视图的布局。如果它是风景照片,则标题较小 - 只是照片底部的一条线。如果她选择一张肖像照片,那么我可以使用足够的空间放置照片侧面的标题,因此标题更大。
如果用户将照片方向从纵向更改为横向,则我要截断文本,然后允许她对其进行编辑以使其有意义。我可以摧毁它,但我宁愿保留它以减少她的打字。
答案 0 :(得分:3)
我编写了以下递归方法和公共API来正确执行此操作。丑陋的软糖因素是this question的主题。
#define kFudgeFactor 15.0
#define kMaxFieldHeight 9999.0
// recursive method called by the main API
-(NSString*) sizeStringToFit:(NSString*)aString min:(int)aMin max:(int)aMax
{
if ((aMax-aMin) <= 1)
{
NSString* subString = [aString substringToIndex:aMin];
return subString;
}
int mean = (aMin + aMax)/2;
NSString* subString = [aString substringToIndex:mean];
CGSize tallerSize = CGSizeMake(self.frame.size.width-kFudgeFactor,kMaxFieldHeight);
CGSize stringSize = [subString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
if (stringSize.height <= self.frame.size.height)
return [self sizeStringToFit:aString min:mean max:aMax]; // too small
else
return [self sizeStringToFit:aString min:aMin max:mean];// too big
}
-(NSString*)sizeStringToFit:(NSString*)aString
{
CGSize tallerSize = CGSizeMake(self.frame.size.width-kFudgeFactor,kMaxFieldHeight);
CGSize stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
// if it fits, just return
if (stringSize.height < self.frame.size.height)
return aString;
// too big - call the recursive method to size it
NSString* smallerString = [self sizeStringToFit:aString min:0 max:[aString length]];
return smallerString;
}
答案 1 :(得分:2)
这实际上并不是一个修复方法,但它确实为计算提供了良好的起点。
如果你使用NSString的sizeWithFont: constrainedToSize: lineBreakMode:
,你的文字会有一个垂直高度。如果按字体的前导高度除以该值,则获得整个字符串中的行数。将[NSString count]除以该数字可以得出每行字符数的近似值。这假设字符串是同质的,如果某人键入(例如)'iiiiiiiiiii ......'选择“MMMMMMMMM ...”,则字符串将不准确。
您还可以使用相关字体的leading
高度划分边界框,以获得适合您的边界框的行数。
每行乘以行数可以为找到适合的文本提供一个起点。
您可以通过对'iiiiii ...'和“MMMMMM ...”字符串进行相同的计算来计算此图中的误差范围。
答案 2 :(得分:1)
我建议采用稍微不同的方法,看看你是否可以使用UILabel而不是较小的UITextView。
可以通过numberOfLines属性将UILabels设置为多行,就像UITextView一样。
UILabels也有一个lineBreakMode属性,我相信该属性的默认值将执行您正在寻找的精确截断效果。
答案 3 :(得分:1)
我认为Jonathan对UILabel有所了解......
因此,用户完成编辑UITextView后,您将获得文本字符串并将其传递给UILabel。您将UITextView的alpha更改为0和/或将其从superview中删除。可能会将未截断的全文存储在ivar中。
UILabels不是“可编辑的”,但您可以通过UILabel(或它的超级视图)检测到触摸。 当您在UILabel上检测到触摸时,您只需恢复隐藏的UITextView并恢复您保存的字符串。
有时SDK很痛苦,但它几乎总能赢得战斗。很多时候,最好将您的设计调整为UIKit约定