UIButton标题标签词包裹尾部截断

时间:2011-09-11 12:52:46

标签: ios uilabel

我需要在UIButton titleLabel上同时启用自动换行和尾部截断。将numberOfLines设置为大于0的值不起作用,文本保持在一行。

我已经四处寻找并且没有找到解决方案。有什么想法吗?

8 个答案:

答案 0 :(得分:41)

这是正确:

lblTemp.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail
lblTemp.numberOfLines = 0;

NSLineBreakMode在NSParagraphStyle.h中定义为:

typedef NS_ENUM(NSInteger, NSLineBreakMode) {       /* What to do with long lines */
    NSLineBreakByWordWrapping = 0,      /* Wrap at word boundaries, default */
    NSLineBreakByCharWrapping,      /* Wrap at character boundaries */
    NSLineBreakByClipping,      /* Simply clip */
    NSLineBreakByTruncatingHead,    /* Truncate at head of line: "...wxyz" */
    NSLineBreakByTruncatingTail,    /* Truncate at tail of line: "abcd..." */
    NSLineBreakByTruncatingMiddle   /* Truncate middle of line:  "ab...yz" */
} NS_ENUM_AVAILABLE_IOS(6_0);

请注意,它是NS_ENUM,而不是NS_OPTION,因此它不能用作掩码。有关详细信息,请参阅this

实际上在这些常量上使用 | 运算符会导致与NSLineBreakByTruncatingTail匹配的掩码:

(NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail) == 4
NSLineBreakByTruncatingTail == 4

据我所知,截断Core Text中的最后一行并且还使用简单的CTFramesetterCreateWithAttributedString&来完成自动换行。 CTFrameDraw API ,但可以通过逐行布局完成,UILabel必须这样做。

iOS 6通过在NSStringDrawing.h中公开新的绘图API来简化这一过程:

typedef NS_ENUM(NSInteger, NSStringDrawingOptions) {
    NSStringDrawingTruncatesLastVisibleLine = 1 << 5, // Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified. Ignored if NSStringDrawingUsesLineFragmentOrigin is not also set.
    NSStringDrawingUsesLineFragmentOrigin = 1 << 0, // The specified origin is the line fragment origin, not the base line origin
    NSStringDrawingUsesFontLeading = 1 << 1, // Uses the font leading for calculating line heights
    NSStringDrawingUsesDeviceMetrics = 1 << 3, // Uses image glyph bounds instead of typographic bounds
} NS_ENUM_AVAILABLE_IOS(6_0);

@interface NSAttributedString (NSExtendedStringDrawing)
- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
@end

因此,如果您使用的是UILabel,您希望NSAttributedString的NSParagraphStyle或标签本身的lineBreakMode设置为:

NSLineBreakByTruncatingTail

标签上的numberOfLines属性必须设置为0.

来自numberOfLines上的UILabel标题:

// if the height of the text reaches the # of lines or the height of the view is less than the # of lines allowed, the text will be
// truncated using the line break mode.

来自UILabel文档:

This property controls the maximum number of lines to use in order to fit the label’s text into its bounding rectangle. The default value for this property is 1. To remove any maximum limit, and use as many lines as needed, set the value of this property to 0.
If you constrain your text using this property, any text that does not fit within the maximum number of lines and inside the bounding rectangle of the label is truncated using the appropriate line break mode.

UILabel这个有点模糊的特性引起的唯一问题是你无法在绘图之前获得大小(这是一些UITableView + UITableViewCell动态布局的必要条件),而无需动态修改NSAttributedString的NSParagraphStyle。 / p>

从iOS 6.1.4开始,调用-boundingRectWithSize:options:带有NSLttributedString且具有NSLineBreakByTruncatingTail换行模式的上下文(对于UILabel),返回不正确的单行高度,即使以下选项传入:

(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine)

(请注意,NSStringDrawingUsesLineFragmentOrigin是多行字符串的必需品。)

更糟糕的是,UILabel的lineBreakMode 覆盖NSAttributedStrings段落样式,因此您必须修改属性字符串的段落样式以进行大小调整计算,然后将其传递给UILabel以便它可以画它。

也就是说,NSLineBreakByWordWrapping for -boundingRectWithSize:options:context和NSLineBreakByTruncatingTail for UILabel(所以它可以在内部使用NSStringDrawingTruncatesLastVisibleLine,或者它用来剪辑最后一行的任何内容)

如果你不想多次改变你的字符串的段落样式,唯一的选择就是做一个简单的UIView子类覆盖-drawRect :(同时将相应的contentMode设置为重绘),并使用iOS 6的新绘图API:

- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);

记住使用NSLineBreakByWordWrapping并传入(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine)作为选项。

最后,在iOS 6之前,如果你想对一个属性字符串进行自动换行+尾部截断,你必须自己使用Core Text进行逐行布局。

答案 1 :(得分:4)

我在发布此问题的同一天解决了问题,将UIButton放在UILabel的{​​{1}}上,numberOfLines设置为3.我离开了这个问题是不确定的,看看是否有人一个更好的主意,但显然没有其他解决方案。

答案 2 :(得分:4)

[self.costomButton.titleLabel setTextAlignment:UITextAlignmentLeft];
[self.costomButton.titleLabel setNumberOfLines:3];

请务必先设置Alignment ps:仅当系统版本大于5.0

时才有效

答案 3 :(得分:0)

尝试将numberOfLines设置为2以上,并相应地设置高度。

    m_button = [UIButton buttonWithType:UIButtonTypeCustom];
[m_button setFrame:CGRectMake(isLandscape?20:10, 40, isLandscape?300:250, 40)];
m_button.titleLabel.font  = [UIFont fontWithName:@"HelveticaNeue" size:17];
[m_btnDiscoverPoint setTitle:@"Title" forState:UIControlStateNormal];
CGRect buttonFrame = [m_button frame];

if ([m_button.titleLabel.text length]>0) {
    CGSize suggestedSize = [m_button.titleLabel.text sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:17] constrainedToSize:CGSizeMake(FLT_MAX,m_button.frame.size.height) lineBreakMode:UILineBreakModeWordWrap];

    if (suggestedSize.width >= self.view.frame.size.width) {
        suggestedSize.width = self.view.frame.size.width-10;
        suggestedSize.height=suggestedSize.height+20;
        m_button.titleLabel.numberOfLines=2;
    }
    else{
        m_button.titleLabel.numberOfLines=1;
    }

    buttonFrame.size.width = suggestedSize.width;

    [m_button setFrame:buttonFrame];
}
[m_button setBackgroundColor:[UIColor clearColor]];
[m_button addTarget:self action:@selector(btnClickAction) forControlEvents:UIControlEventTouchUpInside];

答案 4 :(得分:0)

button.titleLabel.numberOfLines = 2;
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
UIFont * theFont = [UIFont systemFontOfSize: 14]; // you set
CGSize textSize = [titleStr sizeWithAttributes:@{NSFontAttributeName: theFont}];
CGFloat theWidth = kScreenWidth-otherWidthYouSet;// I thought the button's frame is content driving ,and is limited 
CGFloat ratio = theWidth*heightYouSet/((textSize.width+4)*(textSize.height+6));// 4 , 6 , is made by experience . I think the textSize is taken one line text default by the system 
NSUInteger validNum = ratio * titleStr.length;

if(ratio<1){
    [button setTitle: [[titleStr substringToIndex: validNum] stringByAppendingString: @"..."] state: yourState];

}
else{
    [button setTitle: titleStr state: yourState];
}

答案 5 :(得分:0)

快捷键5:

只需在您的 UILabel 上将“ numberOfLines = 2”和“ lineBreakMode”设置为“ truncate tail”,即可将多行尾部截断。

enter image description here

答案 6 :(得分:-2)

您可以使用按位OR运算符在标签上指定多个lineBreakMode。

例如,以下代码将包装标签的文本,并且当文本扩展超出标签框架高度的大小时,将在文本的尾端添加省略号。

lblTemp.lineBreakMode = UILineBreakModeWordWrap | UILineBreakModeTailTruncation;
lblTemp.numberOfLines = 0;

更新:这不正确。它似乎有效,因为枚举中UILineBreakModeWordWrap为0。见下面的评论。

答案 7 :(得分:-2)

iOS中不推荐使用所有UI属性使用NS缩写而不是UI。如此处显示的示例 - NSLineBreakByTruncatingMiddle

相关问题