美文网首页iOS UI相关
实现多行文本的展开&收起

实现多行文本的展开&收起

作者: 独木舟的木 | 来源:发表于2020-09-17 12:01 被阅读0次

    在 B 站的 up 主动态页面中,如果文本的动态内容超过四行,剩下的内容就会被隐藏,末尾会有一个展开按钮。

    展开文本内容后,内容的末尾会有一个收起按钮,可以还原到原来的状态。

    我们可以使用 YYText 框架,实现多行文本的展开/收起逻辑。

    这是我需要展示的一段文本内容:

    Hero 9 Black 的感光器升级到 20MP,让它可以录影最多 5K 30p 的视频,并保留 4K 60p 和 2.7K 240p 的高流畅度录影能力。\nHero 9 Black 的电池容量为 1,720mAh,比上一代提升 30%,且在低温环境下的性能提高。\n内置地平线修正功能,支持 30 秒视频预录,定时拍摄、限时拍摄、实况照片多种模式。还可实现 1080P 视频直播。
    

    默认情况下,假设我的页面最多只能显示三行文本,超出的部分截断不显示。我通过 YYLabel 实现这个 Label 标签:

    首先,在当前视图控制器页面中,导入 <YYKit> 框架,你也可以根据需要只导入 <YYLabel> 框架。

    #import <YYKit.h>
    

    然后将 YYLabel 声明为当前视图控制器下的属性:

    @interface TestViewController ()
    @property (nonatomic, strong) YYLabel *textLabel;
    @end
    

    创建并添加 YYLabel 到当前页面中:

    - (void)addYYLabel {
        self.textLabel = [[YYLabel alloc] init];
        NSString *string = @"Hero 9 Black 的感光器升级到 20MP,让它可以录影最多 5K 30p 的视频,并保留 4K 60p 和 2.7K 240p 的高流畅度录影能力。\nHero 9 Black 的电池容量为 1,720mAh,比上一代提升 30%,且在低温环境下的性能提高。\n内置地平线修正功能,支持 30 秒视频预录,定时拍摄、限时拍摄、实况照片多种模式。还可实现 1080P 视频直播。";
        self.textLabel.text = string;
        self.textLabel.font = [UIFont systemFontOfSize:17.0f];
        self.textLabel.textColor = [UIColor blackColor];
        self.textLabel.numberOfLines = 0;
        self.textLabel.textVerticalAlignment = YYTextVerticalAlignmentTop;
        
        self.textLabel.frame = CGRectMake(0, 0, kScreenWidth - 20, 63);
        self.textLabel.center = self.view.center;
        [self.view addSubview:self.textLabel];
    }
    

    接下来就是,...展开 按钮的实现。首先,...展开 也是一个 YYLabel,我们把这个 YYLabel 设置为整个标签的的truncationToken 截断符即可。

    YYLabel 有一个 truncationToken 属性,如果不设置,就是默认的 ...

    @property (nullable, nonatomic, copy) NSAttributedString *truncationToken;
    

    ...展开 标签的实现如下:

    // MARK: 创建一个有展开/收起按钮的 YYLabel
    - (void)addYYLabel {
        
        // 创建并添加 YYLabel ...
        
        // 创建属性字符串"...展开"
        NSMutableAttributedString *expandString = [[NSMutableAttributedString alloc] initWithString:@"...展开"];
        expandString.font = self.textLabel.font;
    
        NSRange highlightRange = [expandString.string rangeOfString:@"展开"];
        [expandString setColor:[UIColor colorWithRed:0.000 green:0.449 blue:1.000 alpha:1.000]
                         range:highlightRange];
        
        // 创建一个“高亮”属性
        YYTextHighlight *highlight = [YYTextHighlight new];
        [highlight setFont:self.textLabel.font];
        [highlight setColor:[UIColor colorWithRed:0.578 green:0.790 blue:1.000 alpha:1.000]];
        
        // !!!: 点击「展开」按钮,执行的动作
        highlight.tapAction = ^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
            // TODO: 点击展开按钮后,完整显示所有内容
            [self.textLabel sizeToFit];
        };
        [expandString setTextHighlight:highlight range:highlightRange];
        
        // 将属性字符串设置到 YYLabel 中
        YYLabel *expandLabel = [[YYLabel alloc] init];
        expandLabel.attributedText = expandString;
        [expandLabel sizeToFit];
        
        // 将此带高亮属性的 YYLabel 设置为整个 YYLabel 的截断符
        NSAttributedString *truncationToken = [NSAttributedString attachmentStringWithContent:expandLabel contentMode:UIViewContentModeCenter attachmentSize:expandLabel.size alignToFont:expandString.font alignment:YYTextVerticalAlignmentCenter];
        self.textLabel.truncationToken = truncationToken;
    }
    

    ...展开 字符串是一个 NSMutableAttributedString 类型的属性字符串,我在上面附着了点击高亮效果、支持点击执行 Block 代码。
    然后,通过该属性字符串重新创建一个新的 YYLabel 实例对象。
    最后,将该 YYLabel 实例对象设置为整个 YYLabel的截断符,当文本字符串无法完整显示所有内容时,它就会自动显示...展开`。

    接下来,我们继续实现显示完整内容时的“收起”功能。
    “收起” 功能其实很简单,当完全显示所有内容时,就是在整个文本末尾 appendAttributedString: 一个内容为“收起”的属性字符串。

    设置文本内容为“收起”的属性字符串:

    // 创建属性字符串“收起”
    NSMutableAttributedString *collapseString = [[NSMutableAttributedString alloc] initWithString:@"收起"];
    collapseString.font = self.textLabel.font;
    collapseString.color = [UIColor colorWithRed:0.000 green:0.449 blue:1.000 alpha:1.000];
    
    // 创建一个“高亮属性”
    YYTextHighlight *highlight = [YYTextHighlight new];
    [highlight setFont:self.textLabel.font];
    [highlight setColor:[UIColor colorWithRed:0.578 green:0.790 blue:1.000 alpha:1.000]];
    
    // !!!: 点击「收起」按钮,执行的动作
    __weak __typeof(self)weakSelf = self;
    highlight.tapAction = ^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;
        
        // 点击“收起”文本后,重新设置 YYLabel 的尺寸
        strongSelf.textLabel.frame = CGRectMake(0, 0, kScreenWidth - 20, 63);
        strongSelf.textLabel.center = self.view.center;
       // 别忘了,重设整个文本字符串
    };
    [collapseString setTextHighlight:highlight range:collapseString.rangeOfAll];
    

    源码见 GitHub 源码

    相关文章

      网友评论

        本文标题:实现多行文本的展开&收起

        本文链接:https://www.haomeiwen.com/subject/xkllyktx.html