- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我尝试开发自动收缩功能。我已将文本设置为固定大小的 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的描述- 换行发生在单词边界处,除非单词本身不适合单行。
为了您的目的,您应该允许标签适应比它需要的更宽的宽度。但这很困难,因为任务是找到最佳字体大小,而我们无法预测宽度。最好的方法是根据文本中最长的单词找到字体大小。
所以算法:
请在下面找到示例代码(“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/
我有一个 UILabel,其不透明度已通过使用 [UIColor clearColor] 更改为空白我现在想将标签内文本的不透明度更改为尽可能完整的级别。我该怎么做? 最佳答案 使用以下代码更改UIL
我在同一个站点中阅读了如何插入和 UILabel(子类 UILabel 并覆盖所需的方法)。在将它添加到我的应用程序之前,我决定在一个独立的测试应用程序中对其进行测试。代码如下所示。 这是 MyUIL
NSString *longStr = @"AAAAAAAAAA\nBBBBB\nCCCCCCCCCCCCCCCCCC"; 如何使用 UILabel 截断某些标签宽度: AAA... BBB...
我想在 UILabel.text 上有一个纹理。 这样做我对 UILabel 进行了子类化。使用 -drawTextInRect 方法,我尝试仅获取用于使用 CGImageMaskCreate 函数创
我正在尝试使用 iOS 6.0 中新的自动布局 api 构建动态布局。我尝试构建的布局有 2 个按钮,它们之间有一个标签,如下图所示: 我想要的是以灰色显示的容器 View 根据标签中的文本量增加或减
我不知道这是否是我做错了什么,但每次 iOS 6 到 7、7 到 8 以及从 8 到 9 的重大更新时,一些 UILabel 似乎不够大,我看到“...”因为标签被截断了。我现在必须通过应用程序并重置
我偶然发现了一个我不确定如何解决的问题。 正如您在此处看到的名称应该所在的标签(我从用户输入中获取名称,这意味着它是动态的)。如果写得太长,它只会覆盖其他标签。 此外,在 Storyboard中,UI
我是初学者,所以对于任何似乎被忽视或简单的事情,我深表歉意。 基本上,我想要做的是让屏幕上的日期选择器更新 UILabel,然后获取更新 UILabel 的结果并将其推回到前一个屏幕上的另一个 UIL
我有一个 UILabel 的 NSMutableArray。我需要能够在用户触摸时选择此 NSMutableArray 中的特定 UILabel,并将此触摸 UILabel 的中心移动到用户将手指拖动
我知道对于类的元素 UIButton和 UIBarButtonItem他们自动假设window.tintColor作为主要颜色,如果我在应用程序中随时为窗口设置新的 tintColor,则会立即更改。
我是开发者世界的新人,自 2 月份以来一直断断续续地使用 swift 和 Xcode。我希望有人能帮助我。我正在尝试制作一个简单的小费计算器,但似乎无法将两个 uilabels 放在一起。这就是我到目
我有一个单元格原型(prototype),我正在尝试向其添加两个标签。我有两个紧挨着的标签,但标签的大小是动态的,所以我希望第二个标签能够根据第一个标签的大小移动。 基本上,我希望两个标签之间有一个固
这个问题看起来很平常..但是我昨天遇到了问题,我在 xib 中添加了一个标签并为其创建了导出,我想要在该标签内有多行,按钮,所以我决定添加新的子里面有标签... UILabel *label; lab
我正在尝试实现一个可以更改 uilabel 字体大小的功能,我可以缩放 uilabel 大小(即 uilabel.size),然后自动更改 uilabel 的字体大小,示例应用程序是 InstaTex
如果我设置bottomLabel.text = Chinese character,当我运行它时我看不到aboveLabel,如果我调试 View 层次我可以看到它。so有什么问题吗? UIL
我不太确定标题是否符合我的要求,但我有一个带有一堆句子的 label,我想将它们中的每一个分开到不同的 UILabel 这是我的代码 var s: [String] = [] for (i
当我更改 UILabel 的文本属性时,它只会在应用程序中部分更新。 我试过将它放在 viewDidLoad 函数和单独的专用函数中,但无济于事。如果我在更新后将 Label.text 打印到控制台,
我正在尝试使用自动布局对齐两个 UILabel,其中第一个标签没有设置宽度但使用固有内容大小,第二个应该与第一个宽度相同,将文本换行。 理想情况下,第二个标签应将数字行设置为 0 以使用动态类型,但我
我有几个标签,它们永远不应该相互接触。见下图(忽略黄色字母): 一共是4个标签,2个选手名字,2个分数。球员的名字将取代原来的球员标签文本。所以“玩家 1:”可以是任意宽度的任意文本。标签在 View
我正在开发一个应用程序,我需要能够点击并拖动 UILabels。第二个挑战是我需要屏幕上的其他 UILabel 相互移开(切勿重叠)。因此,当我拖动一个标签并遇到另一个标签时,它会将第二个标签撞开。也
我是一名优秀的程序员,十分优秀!