ios - 减少多行 UILabel 中最后一行的宽度

标签 ios objective-c cocoa-touch uilabel

我正在实现一个“阅读更多”功能,很像 Apple 的 AppStore 中的功能。但是,我使用的是多行 UILabel。查看 Apple 的 AppStore,他们如何减小最后可见行的宽度以适应“更多”文本并仍然截断尾部(见图)?

iBooks example image from AppStore

最佳答案

这似乎可行,至少在我进行的有限测试中是这样。有两种公共(public)方法。如果您有多个标签都具有相同行数,则可以使用较短的标签——只需更改顶部的 kNumberOfLines 以匹配您想要的内容。如果您需要传递不同标签的行数,请使用更长的方法。请务必将您在 IB 中制作的标签的类别更改为 RDLabel。使用这些方法代替 setText:。如有必要,这些方法将标签的高度扩展到 kNumberOfLines,如果仍然被截断,将扩展它以适应触摸时的整个字符串。目前,您可以触摸标签中的任何位置。改变它应该不会太难,所以只有靠近 ...Mer 才会导致膨胀。

#import "RDLabel.h"
#define kNumberOfLines 2
#define ellipsis @"...Mer ▾ "

@implementation RDLabel {
    NSString *string;
}

#pragma Public Methods

- (void)setTruncatingText:(NSString *) txt {
    [self setTruncatingText:txt forNumberOfLines:kNumberOfLines];
}

- (void)setTruncatingText:(NSString *) txt forNumberOfLines:(int) lines{
    string = txt;
    self.numberOfLines = 0;
    NSMutableString *truncatedString = [txt mutableCopy];
    if ([self numberOfLinesNeeded:truncatedString] > lines) {
        [truncatedString appendString:ellipsis];
        NSRange range = NSMakeRange(truncatedString.length - (ellipsis.length + 1), 1);
        while ([self numberOfLinesNeeded:truncatedString] > lines) {
            [truncatedString deleteCharactersInRange:range];
            range.location--;
        }
        [truncatedString deleteCharactersInRange:range];  //need to delete one more to make it fit
        CGRect labelFrame = self.frame;
        labelFrame.size.height = [@"A" sizeWithFont:self.font].height * lines;
        self.frame = labelFrame;
        self.text = truncatedString;
        self.userInteractionEnabled = YES;
        UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(expand:)];
        [self addGestureRecognizer:tapper];
    }else{
        CGRect labelFrame = self.frame;
        labelFrame.size.height = [@"A" sizeWithFont:self.font].height * lines;
        self.frame = labelFrame;
        self.text = txt;
    }
}

#pragma Private Methods

-(int)numberOfLinesNeeded:(NSString *) s {
    float oneLineHeight = [@"A" sizeWithFont:self.font].height;
    float totalHeight = [s sizeWithFont:self.font constrainedToSize:CGSizeMake(self.bounds.size.width, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping].height;
    return nearbyint(totalHeight/oneLineHeight);
}

-(void)expand:(UITapGestureRecognizer *) tapper {
    int linesNeeded = [self numberOfLinesNeeded:string];
    CGRect labelFrame = self.frame;
    labelFrame.size.height = [@"A" sizeWithFont:self.font].height * linesNeeded;
    self.frame = labelFrame;
    self.text = string;
}

关于ios - 减少多行 UILabel 中最后一行的宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15113461/

相关文章:

ios - 当 UITextField 的 "editingDidBegin"控件事件触发时,将 UITextField 的当前值设置为属性

ios - 如何动态为按钮分配方法

javascript - 在 Webkit 之外寻找 Javascript 引擎

iphone - 消息发送到应该存在的对象上的已释放实例

iphone - 自定义UISlider(跟踪图片高度)

ios - 具有场景委托(delegate) iOS 13 的多个 Storyboard文件

ios - 如何让函数暂停直到 NSTimer 选择器完成?

ios - 如何解决 iOS Team Provisioning Profile 警告

ios - 在 iPhone 应用程序中使用 Twitter 登录

cocoa-touch - 使用 modalPresentationStyle 显示 View