iOS - 类似朋友圈的社交界面实现

本文介绍如何在iOS应用中实现类似朋友圈的动态评论功能,包括回复、查看评论详情、显示图片等。遵循MVC架构,通过创建包含数据模型和frame模型的Cell,动态计算每个评论单元的高度,确保界面的灵活性和复杂性。详细讲解了数据模型的构建、Frame模型的设置以及Cell的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

社交界面
公司在做一个报修工单的功能,其中主要功能点在于,这个功能不完全是静态显示的,
它还可以点击回复,在下面增加评论,可以点击查看评论详情,也可以收回评论详情,
评论可以带图片,也可以不带图片,工单内容可以带图片,也可以不带图片。
并且回复内容的条数也不确定,就是因为这样的不确定性,一定程度增加了开发的难度。

根据MVC的思想,最初Cell应该自带一个数据模型dataModel,单现在我们多增加一个Frame模型,
frame模型里面包含了各个子控件的frame值,并且自带数据模型dataModel属性,
我们就是在设置dataModel的时候 给frame计算每一个cell的高度

首先我们要准备数据模型,有了数据模型,才能计算文字的大小,才能得到Frame模型
以下是数据模型的代码:

#import <Foundation/Foundation.h>

@interface RepairOrderModel : NSObject

@property (nonatomic,strong) NSString * repair_id;
@property (nonatomic,strong) NSString * faddress;
@property (nonatomic,strong) NSArray * comment_imag_list;
@property (nonatomic,strong) NSString * fservicecontent;
@property (nonatomic,strong) NSString * frealname;
@property (nonatomic,strong) NSString * fordernum;
@property (nonatomic,strong) NSString * power_do;
@property (nonatomic,strong) NSString * fusername;
@property (nonatomic,strong) NSString * fcreatetime;
@property (nonatomic,strong) NSString * fstatus;
@property (nonatomic,strong) NSArray * reply_list;
@property (nonatomic,strong) NSArray * repairs_imag_list;
@property (nonatomic,strong) NSString * comment_score;
@property (nonatomic,strong) NSString * normal_do;
@property (nonatomic,strong) NSString * comment_content;
@property (nonatomic,strong) NSString * fremindercount; // 加急状态

-(instancetype)initWithDict:(NSDictionary *)dict;
+(instancetype)repairModelWithDict:(NSDictionary *)dict;
@end

先来看看Frame模型的代码:
在.h文件里:

#import <Foundation/Foundation.h>
#import "RepairViewFrame.h" // 回复评论列表的区域frame
@class RepairOrderModel;
@interface RepairOrderFrame : NSObject
/** 是否展开回复 默认是NO*/
@property (nonatomic,assign) BOOL isOpenReply;

/**
 *  头像的frame  ,结构体用assin
 */
@property (nonatomic, assign, readonly) CGRect iconF;
/**
 *  业主名的frame
 */
@property (nonatomic, assign, readonly) CGRect nameF;
/**
 *  订单时间的frame
 */
@property (nonatomic, assign, readonly) CGRect timeF;
/**
 *  订单内容的frame
 */
@property (nonatomic, assign, readonly) CGRect desF;
/**
 *  业主地址的frame
 */
@property (nonatomic, assign, readonly) CGRect addF;
/**
 *  订单号码的frame
 */
@property (nonatomic, assign, readonly) CGRect orderNumF;
/**
 *  加急状态的frame
 */
@property (nonatomic, assign, readonly) CGRect urgentF;
/**
 *  配图1的frame
 */
@property (nonatomic, assign, readonly) CGRect image1ListF;
/**
 *  配图2的frame
 */
@property (nonatomic, assign, readonly) CGRect image2ListF;
/**
 *  配图3的frame
 */
@property (nonatomic, assign, readonly) CGRect image3ListF;
/**
 *  派单按钮的frame
 */
@property (nonatomic, assign, readonly) CGRect sendOrdersBtnF;
/**
 *  派单状态的frame
 */
@property (nonatomic, assign, readonly) CGRect sendStateF;
/**
 *  接受按钮的frame
 */
@property (nonatomic, assign, readonly) CGRect acceptBtnF;
/**
 *  评论按钮的frame
 */
@property (nonatomic, assign, readonly) CGRect commandBtnF;
/**
 *  评论数量的frame
 */
@property (nonatomic, assign, readonly) CGRect countLabelF;
/**
 *  详情按钮的frame
 */
@property (nonatomic, assign, readonly) CGRect detailBtnF;
/**
 *  回复区域的frame
 */
@property (nonatomic, assign, readonly) CGRect commandViewF;
/**
 *  回复区域内部的frame模型数组 装RepairViewFrame 模型
 */
@property (nonatomic,strong) NSMutableArray * repairViewFrameArr;

//@property (nonatomic, assign, readonly) RepairViewFrame * commandFrameModel;


/**
 *  cell的高度
 */
@property (nonatomic, assign, readonly) CGFloat cellHeight;

@property (nonatomic, strong) RepairOrderModel *model;    //只有拿到模型数据才能算这些属性的frame,readonly:在这个模型里面的frame属性别人不能乱改,只能访问
@end

因为我这个页面比较复杂 子控件比较多 所以属性也很多
注意:我这里还有一个属性是repairViewFrameArr 这个是装载我回复区域的每一条回复的Frame
我把回复区域的每一条回复单独做了另外一个View,所以每一个回复View就要对应一个回复Frame
我就把所有回复的Frame装在这个数组里。(如果你们的页面没有回复区域,此处省略)

在设置Frame模型的实现文件.m里
切记,在Frame模型中计算大小设置的字号应该和cell中展现一样

// 小号字体
#define SmallFont [UIFont systemFontOfSize:12]
// 中号字体
#define MiddleFont [UIFont systemFontOfSize:14]
// 正常字体
#define LargeFont [UIFont systemFontOfSize:16]


#import "RepairOrderFrame.h"  
#import "RepairOrderModel.h"  // 数据模型
@implementation RepairOrderFrame

-(instancetype)init{
    if (self = [super init]) {
        self.isOpenReply = NO;
        self.repairViewFrameArr = [NSMutableArray array];   //回复数组(里面装载回复的Frame模型)
    }
    return self;
}

/**
 *  计算文字尺寸
 *
 *  @param text    需要计算尺寸的文字
 *  @param font    文字的字体
 *  @param maxSize 文字的最大尺寸
 */
- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
{
    NSDictionary *attrs = @{NSFontAttributeName : font};
    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}


- (void)setModel:(RepairOrderModel *)model  //重写set方法,接收模型数据为本类的属性赋值
{
    _model = model;

    // 子控件之间的间距
    CGFloat padding = 10;

    // 1.头像
    CGFloat iconX = padding;
    CGFloat iconY = padding;
    CGFloat iconW = 40;
    CGFloat iconH = 40;
    _iconF = CGRectMake(iconX, iconY, iconW, iconH);

    // 2.业主名字
    CGSize nameSize = [self sizeWithText:self.model.frealname font:LargeFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
    CGFloat nameX = CGRectGetMaxX(_iconF) + padding;
    CGFloat nameY = iconY + 10;
    _nameF = CGRectMake(nameX, nameY, nameSize.width, nameSize.height);


    // 3.日期
    CGSize timeSize = [self sizeWithText:self.model.fcreatetime font:SmallFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
    CGFloat timeX = CGRectGetMaxX(_iconF) + padding;
    CGFloat timeY = nameY + nameSize.height;
    _timeF = CGRectMake(timeX, timeY, timeSize.width, timeSize.height);


    // 4.地址
    CGSize addSize = [self sizeWithText:self.model.faddress font:LargeFont maxSize:CGSizeMake(120, MAXFLOAT)];
    CGFloat addX = ScreenWidth - addSize.width - padding;
    CGFloat addY = nameY;
    _addF = CGRectMake(addX, addY, addSize.width, nameSize.height);

    // 5.单号
    CGSize orderNumSize = [self sizeWithText:[NSString stringWithFormat:@"单号:%@",self.model.fordernum] font:SmallFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
    CGFloat orderNumX = ScreenWidth - orderNumSize.width - padding;
    CGFloat orderNumY = timeY;
    _orderNumF = CGRectMake(orderNumX, orderNumY, orderNumSize.width, orderNumSize.height);

    // 6.加急
    CGSize urgentSize = [self sizeWithText:@"加急
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值