gpt4 book ai didi

ios - 如何知道 UILabel 中的单词是否被剪切

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:16:04 25 4
gpt4 key购买 nike

我尝试开发自动收缩功能。我已将文本设置为固定大小的 UILabel。之后,我降低字体大小并检查文本是否适合给定的容器大小。

问题是如果单词长于容器宽度,UILabel 会忽略 NSLineBreakByWordWrapping。导致我把尾词删掉了。

代码如下:

- (void) setCardText:(NSString *)txt {
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:txt];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
[paragraphStyle setAlignment:NSTextAlignmentCenter];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [txt length])];
self.cardLabel.attributedText = attributedString;

for (CGFloat fontSize = 40; fontSize >=5; fontSize--) {
[self.cardLabel setFont:[UIFont fontWithName:@"GothamPro-Light" size:fontSize]];
[paragraphStyle setLineSpacing:fontSize*0.3f];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [txt length])];
self.cardLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.cardLabel sizeToFit];
if (self.cardLabel.frame.size.width <= 220) {
[self.cardLabel setFrame:CGRectMake(40, 40, 220, self.cardLabel.frame.size.height)];
}
if (self.cardLabel.frame.size.height <= 210) {
[self.cardLabel setFrame:CGRectMake(40, 40, self.cardLabel.frame.size.width, 210)];
}
if (self.cardLabel.frame.size.width <= 220 && self.cardLabel.frame.size.height <= 210) {
[self.cardLabel setFrame:CGRectMake(40, 40, 220, 210)];
break;
}
};

结果如下(抱歉截屏是俄语):http://take.ms/kg2mG

在第三行中,单词被剪切,其结尾移至下一行。

我猜这是因为最初这个词不适合容器宽度,被强行分成两半。我想我需要某种切词检测器,它告诉我继续降低字体大小。或者另一种猜测是强制 UILabel 被“unfit word”扩展。但我找不到任何东西可以完成这项工作。

我还可以将给定的字符串分解成单词,并检查每个单词是否适合容器宽度。但我认为这种方法是在发明轮子。有什么我遗漏的东西可以轻松解决我的问题吗?

最佳答案

sizeToFit 方法调用 sizeThatFits: 返回“最佳”大小以适应当前 边界,然后调整标签大小。所以首先你约束标签并且它必须适合给定的宽度。可以看到NSLineBreakByWordWrapping的描述- 换行发生在单词边界处,除非单词本身不适合单行。

为了您的目的,您应该允许标签适应比它需要的更宽的宽度。但这很困难,因为任务是找到最佳字体大小,而我们无法预测宽度。最好的方法是根据文本中最长的单词找到字体大小。

所以算法:

  1. 检测最长的单词,以空格分隔。
  2. 迭代地减小字体大小并计算大于所需宽度的最长单词的大小。
  3. 将计算字体设置为全文并调用 sizeThatFits。

请在下面找到示例代码(“Verdana”字体用于测试)

- (void) setText {
NSString * text = @"Incidental, indirect, secondary, side rival - Побочный, косвенный, второстепенный, боковой соперник";
CGFloat maxWidth = 300.;
[self setText:text toLabel:self.label maxWidth:maxWidth];
}

- (void) setText:(NSString *)text
toLabel:(UILabel*)label
maxWidth:(CGFloat)maxWidth
{
CGFloat fontSize = [self fontSizeOfWord:[self theLongestWord:text]
initialFontSize:40.
constrainedByWidth:maxWidth];

NSMutableAttributedString * attributedString = [self attributedStringForText:text];
[self setupAttributedStirng:attributedString withFontWithSize:fontSize];
label.attributedText = attributedString;
CGRect labelFrame = label.frame;
labelFrame.size = [label sizeThatFits:[attributedString sizeAdaptedForWidth:maxWidth]];
label.frame = labelFrame;
}

- (NSString*) theLongestWord:(NSString*)text {
NSArray * words = [text componentsSeparatedByString:@" "];
NSUInteger longestLength = 0;
NSUInteger index = NSNotFound;
for(int i = 0; i < words.count; i++) {
NSString * word = words[i];
CGFloat length = word.length;
if(length > longestLength) {
longestLength = length;
index = i;
}
}
return (index != NSNotFound ? words[index] : nil);
}

- (CGFloat)fontSizeOfWord:(NSString *)word
initialFontSize:(CGFloat)initialFontSize
constrainedByWidth:(CGFloat)maxWidth
{
NSMutableAttributedString * wordString = [self attributedStringForText:word];
CGFloat fontSize = initialFontSize;
for (; fontSize >= 5.; --fontSize) {
[self setupAttributedStirng:wordString
withFontWithSize:fontSize];
CGSize wordSize = [wordString sizeAdaptedForWidth:CGFLOAT_MAX];
if(wordSize.width <= maxWidth){
break;
}
}
return fontSize;
}

- (NSMutableAttributedString*) attributedStringForText:(NSString*)text {
return (text&&text.length ? [[NSMutableAttributedString alloc] initWithString:text]:nil);
}

- (void)setupAttributedStirng:(NSMutableAttributedString *)attributedString
withFontWithSize:(CGFloat)fontSize
{
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
[paragraphStyle setAlignment:NSTextAlignmentCenter];
UIFont * font = [UIFont fontWithName:@"Verdana" size:fontSize];
[paragraphStyle setLineSpacing:fontSize*0.3f];
NSDictionary * attributes = @{NSParagraphStyleAttributeName: paragraphStyle,
NSFontAttributeName: font};
[attributedString addAttributes:attributes
range:NSMakeRange(0, [attributedString length])];
}

NSAttributedString 的类别:

@implementation NSAttributedString (AdaptedSize)

- (CGSize) sizeAdaptedForWidth:(CGFloat)width
{
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self);
CGSize targetSize = CGSizeMake(width, CGFLOAT_MAX);
CGSize fitSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
CFRangeMake(0, [self length]),
NULL, targetSize, NULL);
CFRelease(framesetter);
return fitSize;
}

@end

关于ios - 如何知道 UILabel 中的单词是否被剪切,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28882511/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com