iOS 文本展开收起

经常会遇到类似微信的展开收起,本身这个逻辑是比较清晰的,动态变换文本的高度就可以,但实际操作过程中,却会有各种坑,最令人蛋疼的就是抖动,下面简述下自己的采坑之路

一、给定文本一个限定高度(比如:90),小于等于90就取90,大于90默认收起,点击展开取真实高度,点击收起,取90。这样的做法是直接拿到内容就计算出高度,变高度。

以下5种方法经测验方案5抖动最小属于偶发性质且很不明显(抖动的根本原因在于文本的高度是可变的,在偶发情况下可能刚好使cell的高度在一个临界值:比如差零点几个像素之类的,然后微调,就会影响lale,因为别的都是明确的固定值,只有这个是小数后好几位)

1、使用文本的boundingRectWithSize计算文本高度

2、使用字体、行间距计算文本高度(本质是由boundingRectWithSize算出行数然后再算出高度)

3、使用YYTextLayout计算文本高度(本质是自己绘制)

4、使用属性字符串计算高度

5、使用viewsystemLayoutSizeFittingSize 或者 sizeThatFits获取高度(获取到的就是真实展示时的高度)。

     5-1、iOS11之后可以直接在赋值方法里获取高度(因为iOS11之后,UITableView会先走

              -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;再走 

               - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;即先赋值再算高度---类似安卓。

               而在iOS11之前是先走高度再赋值的,所以才     有一直以来的算高度哈)。

     5-2、拿到数据后创建一个跟展示lable一样的lable,赋值然后获取高度

#import <YYKit/NSAttributedString+YYText.h>
@implementation NSString (Size)

//  1、-------------直接计算文本高度--------
+ (CGFloat)getStrH:(CGFloat ) maxW Str:(NSString *)str andFont:(NSInteger) font
{
    if (!str.length) return 0;
    CGRect itemFrame = [str boundingRectWithSize:CGSizeMake(maxW, CGFLOAT_MAX) options: NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading  attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:font]} context:nil];
    return  itemFrame.size.height;
    
}
//  向上取整高度
+ (CGFloat)getStrCeilH:(CGFloat ) maxW Str:(NSString *)str andFont:(NSInteger) font
{
    if (!str.length) return 0;
    CGRect itemFrame = [str boundingRectWithSize:CGSizeMake(maxW, CGFLOAT_MAX) options: NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading  attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:font]} context:nil];
    CGSize size = itemFrame.size;
//    一定程度能够防止减轻抖动
    return ceil(size.height);
    
}


//  2、-----------根据字体、行间距和constrainedWidth计算文本高度--------
- (CGFloat)getStrH:(UIFont*)font
       lineSpacing:(CGFloat)lineSpacing
  constrainedWidth:(CGFloat)constrainedWidth {
    
    if (!self.length) {
        return 0;
    }
    CGFloat oneLineHeight = font.lineHeight;
    CGSize textSize = [self boundingRectWithSize:CGSizeMake(constrainedWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size;
    
    CGFloat rows = textSize.height / oneLineHeight;
    CGFloat realHeight = (rows * oneLineHeight) + (rows - 1) * lineSpacing;
    return  realHeight;
}

// 有行间距 向上取整高度
- (CGFloat)getStrCeilH:(UIFont*)font
       lineSpacing:(CGFloat)lineSpacing
  constrainedWidth:(CGFloat)constrainedWidth {
    
    if (!self.length) {
        return 0;
    }
    CGFloat oneLineHeight = font.lineHeight;
    CGSize textSize = [self boundingRectWithSize:CGSizeMake(constrainedWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size;
    
    CGFloat rows = textSize.height / oneLineHeight;
    CGFloat realHeight = (rows * oneLineHeight) + (rows - 1) * lineSpacing;
    return  ceil(realHeight);
}

- (CGFloat)getStrH:(UIFont*)font
       lineSpacing:(CGFloat)lineSpacing
  constrainedWidth:(CGFloat)constrainedWidth
         limitRows:(NSInteger) limitRows{
    
    if (!self.length) {
        return 0;
    }
    CGFloat oneLineHeight = font.lineHeight;
    CGSize textSize = [self boundingRectWithSize:CGSizeMake(constrainedWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size;
    
    CGFloat rows = textSize.height / oneLineHeight;
    if (limitRows > 0 && rows > limitRows) {
        rows = limitRows;
    }
    CGFloat realHeight = (rows * oneLineHeight) + (rows - 1) * lineSpacing;
    return  realHeight;
}

// 3、-------YYTextLayout 使用frame计算准确 自动布局会有误差--------
- (YYTextLayout*)getYYTextLyout:(UIFont*)font
                    lineSpacing:(CGFloat)lineSpacing
            constrainedWidth:(CGFloat)constrainedWidth {
    if (!self.length) {
        return 0;
    }
    NSMutableAttributedString *attriStr = [[NSMutableAttributedString alloc] initWithString:self];
    attriStr.lineSpacing = lineSpacing;
    attriStr.font = font;
//    attriStr.lineBreakMode = NSLineBreakByTruncatingTail;
    CGSize maxSize = CGSizeMake(constrainedWidth, MAXFLOAT);
    YYTextLayout *contentLayout = [YYTextLayout layoutWithContainerSize:maxSize text:attriStr];
    return  contentLayout;
}
 // 5-1示例
//    CGSize textSize = [self.textContentL systemLayoutSizeFittingSize:CGSizeMake(self.contentView.frame.size.width-20, 1000)];
     CGSize textSize = [self.textContentL sizeThatFits:CGSizeMake(self.contentView.frame.size.width-20, 1000)];
    self.model.height = textSize.height+181+height_collectionview;
// 5-2示例
-(void)setIsShowMore:(BOOL)isShowMore {
    _isShowMore = isShowMore;
    UILabel *temp = [[UILabel alloc] init];
    temp.text = self.textContent;
    temp.font = [UIFont systemFontOfSize:15 weight:(UIFontWeightLight)];
    [temp setColumnSpace:2.0];
    [temp setRowSpace:5];
    //    temp.numberOfLines = 0;
    if (isShowMore) {
        temp.numberOfLines = 0;
    } else {
        temp.numberOfLines = 3;
    }
    CGFloat w = [UIScreen mainScreen].bounds.size.width - 20;
    CGFloat h = MAXFLOAT;
    CGFloat height = ceil([temp sizeThatFits:CGSizeMake(w, h)].height);
    //    NSDictionary *dict = @{NSFontAttributeName: [UIFont systemFontOfSize:17]};
    //    CGFloat height = [title boundingRectWithSize:CGSizeMake(w, h) options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size.height;
    self.height = height+181+300;
}

二、给文本一个固定行数(比如:3行),小于等于3行,正常显示,大于3行默认3行,点击展开真实行数,点击收起3行。这种方案要结合UITableView的高度自适应UITableViewAutomaticDimension(

_tableView.rowHeight = UITableViewAutomaticDimension;

_tableView.estimatedRowHeight = 50; // 这个给不给都可以

)。这样就不再关心- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;方法。完全让系统自动调整

。这样的效果取决于计算出行数的方法。下面简述两种方式,方案不唯一,只要能换算出行数就可以。实测方案一效果跟变高度的方案5效果相似,比较理想。

1、使用systemLayoutSizeFittingSize/sizeThatFits获取行数

//获取文字所需行数
- (NSInteger)needLinesWithWidth:(CGFloat)width currentLabel:(UILabel *)currentLabel {
    UILabel *label = [[UILabel alloc] init];
    label.font = currentLabel.font;
    NSString *text = currentLabel.text;
    NSInteger sum = 0;
    //加上换行符
    NSArray *rowType = [text componentsSeparatedByString:@"\n"];
    for (NSString *currentText in rowType) {
        label.text = currentText;
        //获取需要的size
//        CGSize textSize = [label systemLayoutSizeFittingSize:CGSizeZero];
        CGSize textSize = [label sizeThatFits:CGSizeZero];
        NSInteger lines = ceil(textSize.width/width);
        lines = lines == 0 ? 1 : lines;
        sum += lines;
    }
    return sum;
}

2、使用boundingRectWithSize算出行数

转载于:https://www.cnblogs.com/lijianyi/p/11496476.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: iOS 文本可以通过使用 NSAttributedString 和 NSTextAttachment 类加载 GIF 图片,达到将文本与动态效果结合的效果。 首先,需要将 GIF 图片转换为 NSData 格式,可通过使用 NSData 的类方法 dataWithContentsOfFile 或者 dataWithContentsOfURL 来实现。 接着,创建 NSTextAttachment 实例,并以 NSData 格式将 GIF 图片作为参数传入。然后,创建 NSMutableAttributedString 实例,并将文本内容包含在其中。 最后,使用 UILabel、UITextView 或者 UIWebView 等组件来展示文本内容,并加以控制动态效果的播放周期及重复次数等属性,达到更丰的用户体验。 需要注意的是,在使用文本加载 GIF 图片时,应考虑对应用性能及网络耗费等问题进行优化调整,使得应用流畅稳定,并能够节省用户移动数据流量等资源。 ### 回答2: iOS开发中,要加载gif动图作为文本,可以使用如下的步骤: 1. 引入SDWebImage库:在项目中添加SDWebImage库,这是一个常用的图片加载库,可以方便地加载并显示网络上的图片。 2. 下载gif图片:从网络上找到合适的gif图片,并将其下载到本地。 3. 将gif图片添加到文本中:使用SDWebImage提供的方法将gif图片添加到文本中,可以使用`UIImage sd_animatedGIFWithData:`方法将本地的gif图片转换为UIImage对象,并使用该UIImage对象创建一个`NSTextAttachment`对象。 4. 将NSTextAttachment对象添加到NSAttributedString中:将创建好的NSTextAttachment对象添加到NSMutableAttributedString对象中,可以使用`appendAttributedString:`方法将其追加到NSMutableAttributedString对象的末尾。 5. 将NSAttributedString对象显示在界面上:通过UILabel、UITextView等界面控件,将NSMutableAttributedString对象显示在界面上,即可完成文本加载gif的功能。 需要注意的是,为了保证gif动图的流畅播放,SDWebImage库会将gif图片展示为一系列的静态图片,然后再按照正确的帧率进行播放。另外,对于高性能的gif加载,也可以使用其他优化库,如FLAnimatedImage等。 综上所述,通过引入SDWebImage库、下载gif图片、将图片添加到文本中,并将文本显示在界面上等一系列步骤,即可实现在iOS中加载gif动图作为文本显示的功能。 ### 回答3: 在iOS中,要加载GIF图像并将其显示在文本中,我们可以采取以下步骤: 1. 首先,我们需要获取GIF图像文件的URL或路径。可以从互联网上下载或从应用程序的资源文件中获取。例如,如果GIF图像保存在应用程序的资源文件中,则可以使用`Bundle.main.url(forResource: "myGif", withExtension: "gif")`方法获取该文件的URL。 2. 接下来,我们需要将GIF图像文件加载到`Data`对象中,以便将其与`NSAttributedString`文本一起使用。我们可以使用`Data(contentsOf: gifURL)`方法将URL转换为Data对象。 3. 然后,我们可以创建一个`NSTextAttachment`对象,并将GIF图像数据设置为其`image`属性。例如,可以使用`NSTextAttachment(image: UIImage(data: gifData)!)`来创建`NSTextAttachment`对象。 4. 然后,我们可以使用`NSAttributedString`的`append`方法将`NSTextAttachment`对象添加到文本中,并设置其适当的位置。例如,可以使用`attributedString.append(NSAttributedString(attachment: textAttachment))`语句将`NSTextAttachment`对象添加到`attributedString`文本字符串中。 5. 最后,我们可以将包含GIF图像的文本字符串应用于文本视图或标签等UI元素,以便在界面上显示GIF图像。例如,对于UILabel,可以使用`label.attributedText = attributedString`将文本字符串应用于标签。 综上所述,以上是利用iOS文本加载GIF的简要步骤。通过将GIF图像文件加载到`Data`对象中,然后将其作为`NSTextAttachment`对象添加到文本字符串中,我们可以在文本中显示GIF图像,并将其应用于iOS界面中的相应UI元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值