您的位置:首页 > 产品设计 > UI/UE

长文本在复杂cell里的收缩与展开

2017-06-03 00:17 288 查看
一般情况下,我们在cell里处理单纯的长文本收缩与展开是不难的,但是遇到一些复杂cell的时候,里面有各种uilabe、uiimageview、图片、声音、视频时,问题就变得比较复杂,因为你处理了cell里其中一个长文本时,其他cell里的元素得重新布局。

效果如下



由于上传限制,复杂cell的GIF见 GitHub   https://github.com/targetcloud/baisibudejie





实现思路如下:

在MODEL层,保存各种高度数据

//
// TGTopicNewM.h
// baisibudejie
//
// Created by targetcloud on 2017/5/30.
// Copyright © 2017年 targetcloud. All rights reserved.
//

#import <Foundation/Foundation.h>
@class TGUserNewM;
@class TGCommentNewM;
@interface TGTopicNewM : NSObject
@property (nonatomic, copy) NSString *ID;
@property (nonatomic, copy) NSString *type;//audio image video gif text
@property (nonatomic, assign) NSInteger status;
@property (nonatomic, assign) NSInteger up;
@property (nonatomic, assign) NSInteger down;
@property (nonatomic, assign) NSInteger forward;
@property (nonatomic, assign) NSInteger comment;
@property (nonatomic, copy) NSString *share_url;
@property (nonatomic, copy) NSString *passtime;
@property (nonatomic, assign) NSInteger bookmark;
@property (nonatomic, copy) NSString *text;
@property (nonatomic, strong) TGUserNewM *u;

@property (nonatomic, assign) NSInteger video_playfcount;
@property (nonatomic, assign) NSInteger video_width;
@property (nonatomic, assign) NSInteger video_height;
@property (nonatomic, copy) NSString *video_uri;
@property (nonatomic, assign) NSInteger video_duration;
@property (nonatomic, assign) NSInteger video_playcount;
@property (nonatomic, copy) NSString * video_thumbnail;
@property (nonatomic, copy) NSString * video_thumbnail_small;

@property (nonatomic, strong) NSArray<TGCommentNewM *> *top_comments;

@property (nonatomic, copy) NSString * image_medium;
@property (nonatomic, copy) NSString * image_big;
@property (nonatomic, assign) NSInteger image_height;
@property (nonatomic, assign) NSInteger image_width;
@property (nonatomic, copy) NSString * image_small;
@property (nonatomic, copy) NSString * image_thumbnail_small;

@property (nonatomic, copy) NSString * images_gif;
@property (nonatomic, assign) NSInteger gif_width;
@property (nonatomic, copy) NSString * gif_thumbnail;
@property (nonatomic, assign) NSInteger gif_height;

@property (nonatomic, assign) NSInteger audio_playfcount;
@property (nonatomic, assign) NSInteger audio_height;
@property (nonatomic, assign) NSInteger audio_width;
@property (nonatomic, assign) NSInteger audio_duration;
@property (nonatomic, assign) NSInteger audio_playcount;
@property (nonatomic, copy) NSString * audio_uri;
@property (nonatomic, copy) NSString * audio_thumbnail;
@property (nonatomic, copy) NSString * audio_thumbnail_small;

@property (nonatomic, assign,readonly) NSInteger width;
@property (nonatomic, assign,readonly) NSInteger height;
@property (nonatomic, copy,readonly) NSString * image;

@property (nonatomic, assign,readonly) CGFloat cellHeight;
@property (nonatomic, assign,readonly) CGFloat middleY;//用于收缩展开
@property (nonatomic, assign,readonly) CGFloat defaultHeight;//用于收缩展开
@property (nonatomic, assign,readonly) CGFloat textHeight;//用于收缩展开

@property (nonatomic, assign) CGRect middleFrame;
@property (nonatomic, assign, getter=isBigPicture) BOOL bigPicture;

@property (nonatomic, assign, getter=isShowAllWithoutComment) BOOL showAllWithoutComment;//用于评论VC
@property (nonatomic, assign,readonly) CGFloat cellHeightWithoutComment;//用于评论VC

@property (nonatomic, assign) CGFloat picProgress;
@property (nonatomic, assign,getter=is_voicePlaying) BOOL voicePlaying;
@property (nonatomic, assign,getter=is_videoPlaying) BOOL videoPlaying;
@property (nonatomic, assign,readonly) CGFloat commentVH;
@property (nonatomic, copy,readonly) NSMutableAttributedString * attrStrM;
@end

//
// TGTopicNewM.m
// baisibudejie
//
// Created by targetcloud on 2017/5/30.
// Copyright © 2017年 targetcloud. All rights reserved.
//

#import "TGTopicNewM.h"
#import "TGCommentNewM.h"
#import "TGUserNewM.h"

static CGFloat const MiddleHeightConstraint = 300;

@implementation TGTopicNewM
{
CGFloat _cellHeight;//cell高,会变化
CGFloat _defaultHeight;//第一次计算的缺省高度,不变,如长文本未展开前的高度
CGFloat _cellHeightWithoutComment;//没有评论的cell高度(已展开状态)
CGFloat _textHeight;
CGFloat _commentVH;
CGRect _middleFrame;
}

+ (NSDictionary *)mj_objectClassInArray {
return @{
@"top_comments" : [TGCommentNewM class]
};
}

+ (NSDictionary *)mj_replacedKeyFromPropertyName {
return @{
@"ID" : @"id",

@"video_playfcount" : @"video.playfcount",
@"video_width" : @"video.width",
@"video_height" : @"video.height",
@"video_uri" : @"video.video[0]",
@"video_duration" : @"video.duration",
@"video_playcount" : @"video.playcount",
@"video_thumbnail" : @"video.thumbnail[0]",
@"video_thumbnail_small" : @"video.thumbnail_small[0]",

@"image_medium" : @"image.medium[0]",
@"image_big" : @"image.big[0]",
@"image_height" : @"image.height",
@"image_width" : @"image.width",
@"image_small" : @"image.small[0]",
@"image_thumbnail_small" :@"image.thumbnail_small[0]",

@"images_gif" :@"gif.images[0]",
@"gif_width" :@"gif.width",
@"gif_thumbnail" :@"gif.gif_thumbnail[0]",
@"gif_height" :@"gif.height",

@"audio_playfcount" :@"audio.playfcount",
@"audio_height" :@"audio.height",
@"audio_width" :@"audio.width",
@"audio_duration" :@"audio.duration",
@"audio_playcount" :@"audio.playcount",
@"audio_uri" :@"audio.audio[0]",
@"audio_thumbnail" :@"audio.thumbnail[0]",
@"audio_thumbnail_small" :@"audio.thumbnail_small[0]",

};
}

-(NSString * )image{
return [_type isEqualToString:@"video"] ? _video_thumbnail :
[_type isEqualToString:@"image"] ? _image_big :
[_type isEqualToString:@"gif"] ? _gif_thumbnail :
[_type isEqualToString:@"audio"] ? _audio_thumbnail : @"";
}

-(NSInteger) width{
return [_type isEqualToString:@"video"] ? _video_width :
[_type isEqualToString:@"image"] ? _image_width :
[_type isEqualToString:@"gif"] ? _gif_width :
[_type isEqualToString:@"audio"] ? _audio_width : 0;
}

-(NSInteger) height{
return [_type isEqualToString:@"video"] ? _video_height :
[_type isEqualToString:@"image"] ? _image_height :
[_type isEqualToString:@"gif"] ? _gif_height :
[_type isEqualToString:@"audio"] ? _audio_height : 0;
}

- (CGFloat)cellHeight{
if (_cellHeight) return _cellHeight;
_commentVH = 0;
_cellHeightWithoutComment = 0;
_cellHeight += 55;

CGSize textMaxSize = CGSizeMake(ScreenW - 2 * Margin , MAXFLOAT);

_textHeight = [self.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.height + 1;//+1是为了容错
// [self.text sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:textMaxSize].height;
//长文本过长导致高度过高应受到高度约束
_cellHeightWithoutComment = _cellHeight + _textHeight + Margin;
_cellHeight += (_textHeight > TextHeightConstraint ? TextHeightConstraint : _textHeight) + Margin;

if (![self.type isEqualToString: @"text"]) { //图片、视频
CGFloat middleW = textMaxSize.width;
CGFloat middleX = Margin;
CGFloat middleH = middleW * self.height / self.width;
if (middleH >= ScreenH) { // 显示的图片高度超过一个屏幕,就是超长图片
middleH = MiddleHeightConstraint;
_bigPicture = YES;
}
CGFloat middleY = _cellHeight;
_middleY = middleY;
_middleFrame = CGRectMake(middleX, middleY, middleW, middleH);
//TGLog(@"%ld,%ld, %@ , %@ ,%@", self.height, self.width,self.type,self.text, NSStringFromCGRect(_middleFrame))
_cellHeight += middleH + Margin;
_cellHeightWithoutComment += middleH + Margin;
}

if (self.top_comments.count > 0){//评论
textMaxSize = CGSizeMake(ScreenW - 2 * Margin - 10, MAXFLOAT);
NSMutableAttributedString *attrStrM = [[NSMutableAttributedString alloc] init];
for (int i=0 ; i <self.top_comments.count; i++){
TGCommentNewM * com = self.top_comments[i];
NSString *content = com.content;
NSString *username = com.u.name;
NSString *cmtText = [NSString stringWithFormat:@"%@ : %@", username,content];
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString : cmtText];
[attrStr addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:12.0f]
range:NSMakeRange(0, attrStr.length)];
[attrStr addAttribute:NSForegroundColorAttributeName
value:TGColor(62, 114, 166)
range:NSMakeRange(0, username.length)];
[attrStrM appendAttributedString:attrStr];
if (i != self.top_comments.count-1){
[attrStrM appendAttributedString: [[NSAttributedString alloc] initWithString:@"\n"]];
}
_commentVH += [cmtText boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]} context:nil].size.height;
}
_attrStrM = attrStrM;
_cellHeight += (_commentVH + 10);
}
_cellHeight += 35 ;//工具条
_cellHeightWithoutComment += 35;
//TGLog(@"_cellHeight,%@,%@,%f",self.type, self.text, _cellHeight)
_defaultHeight = _cellHeight;
return _cellHeight;
}

- (NSString *)passtime{
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSDate *create = [fmt dateFromString:_passtime];
if (create.isThisYear) { // 今年
if (create.isToday) { // 今天
NSDateComponents *cmps = [[NSDate date] deltaFrom:create];
if (cmps.hour >= 1) { // 时间差距 >= 1小时
return [NSString stringWithFormat:@"%zd小时前", cmps.hour];
} else if (cmps.minute >= 1) { // 1小时 > 时间差距 >= 1分钟
return [NSString stringWithFormat:@"%zd分钟前", cmps.minute];
} else { // 1分钟 > 时间差距
return @"刚刚";
}
} else if (create.isYesterday) { // 昨天
fmt.dateFormat = @"昨天 HH:mm:ss";
return [fmt stringFromDate:create];
} else { // 其他
fmt.dateFormat = @"MM-dd HH:mm:ss";
return [fmt stringFromDate:create];
}
} else { // 非今年
return _passtime;
}
}
@end


在Controller层,设置一个回调Block,或者用代理实现也合理,用于在cell展开或收缩后,能对此cell进行局部刷新
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
TGTopicNewCell *cell = [tableView dequeueReusableCellWithIdentifier:TGTopicCellID];
cell.topic = self.topics[indexPath.row];
//传入block,用于展开收缩
__weak typeof(self)weakSelf = self;
__weak typeof(cell)weakCell = cell;
cell.block = ^ {
weakCell.topic = weakSelf.topics[indexPath.row];
[weakSelf.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];
};
return cell;
}

在Cell层(View),进行按钮的点击,由收缩变展开,由展开变收缩
- (IBAction)spreadBtnClick:(UIButton *)sender {
[self.spreadBtn setTitle: ([self.spreadBtn.currentTitle isEqualToString:@"展开"] ? @"收缩" : @"展开" ) forState:UIControlStateNormal];

self.topic.middleFrame = CGRectMake(self.topic.middleFrame.origin.x,
[self.spreadBtn.currentTitle isEqualToString:@"收缩"] ? self.topic.middleY + (self.topic.textHeight + 19.f - TextHeightConstraint) : self.topic.middleY,
self.topic.middleFrame.size.width,
self.topic.middleFrame.size.height);

[self.topic setValue:@( [self.spreadBtn.currentTitle isEqualToString:@"收缩"] ? self.topic.cellHeight + (self.topic.textHeight + 19.f - TextHeightConstraint) : self.topic.defaultHeight) forKey:@"cellHeight" ];
!(self.block) ? : self.block();
}


完整代码见 https://github.com/targetcloud/baisibudejie
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息