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

iOS开发UI篇 -- 0401微博主页-自定义cell

2015-07-14 23:02 501 查看

一、自定义cell详细步骤介绍

自定义cell,控件不固定(比如微博)

1.新建一个继承自UITableViewCell的类重写initWithStyle:reuseIdentifier:方法

添加所有需要显示的子控件(不需要设置子控件的数据和frame, 子控件要添加到contentView中)

进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片) -- 初始化 ,添加到contentView中,赋值,设置一次性属性(比如字体,vipImage)

2.提供2个模型

数据模型: 存放文字数据\图片数据 -- 和Cell 中的控件相对应,同时和json中数据相对应,有用的数据都存储

frame模型: 存放数据模型\所有子控件的frame\cell的高度 -- 在setModel中设置各个控件的frame,并计算cellHeight;

3.cell拥有一个frame模型(不要直接拥有数据模型) -- 在setModelFrame中settingData 和 settingFrame;

4.在TableViewController提供一个NSArray *modelFrames; 在setting方法中获取网络数据,

-- statusFrame.status = status 在settingStatus中设置status的frame,在HomeViewController中从服务器获取status数据,

5.接下来 数据源 代理(cellHeight)

二、自定义cell最终总结

第一步 新建cell,重写initWithStyle:reuseIdentifier:

第二步 创建Status 和 StatusFrame 模型

Status中的属性和cell中的控件相对应

StatusFrame中装各个控件的 frame 和 cellHeight

第三步 重写setStatus 和 setStatusFrame 方法

重写setStatus,计算各控件 frame 和 cellHeight

重写setStatusFrame方法,settingData 和 settingFrame

第四步 获取Status数据,写数据源和代理方法

ps:cell初始化的时候,初始化所有子控件

对于不一定显示的控件,我们在settingData的时候根据Status中有无此数据来设置该控件是否显示

将其余步骤都完成之后,在计算frame这一步我们可以一个个来计算,减少出错率!

获取到Status数据时,我们可以先NSLog看一看,在转模型,装到Frame中

整个WBTableViewController相当于:我们将33个双色球放到了大箱子中,用到第一个就取出第一个,用到第二个就取第二个。提高了性能,手机界面不会出现卡顿现象

三、demo奉上!

第一步 新建cell,重写initWithStyle:reuseIdentifier:

#import "WBStatusCell.h"

@interface WBStatusCell ()
// 头像
@property(nonatomic,weak)UIImageView *iconImage;

// 昵称
@property(nonatomic,weak)UILabel *nameLable;

// vip
@property(nonatomic,weak)UIImageView *vipImage;

// 正文
@property(nonatomic,weak)UILabel *contentLable;

// 图片
@property(nonatomic,weak)UIImageView *photoImage;
@end

@implementation WBStatusCell

+ (instancetype)cellWithTableView:(UITableView *)tableView{
static NSString *ID = @"status";
WBStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if(cell == nil){
cell = [[WBStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
return cell;
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// 头像
UIImageView *iconImage = [[UIImageView alloc] init];    //  在这里我们初始化控件,添加到contentView中,赋值,设置一次性属性(比如字体,vipImage)
[self.contentView addSubview:iconImage];
self.iconImage = iconImage;

// 昵称
UILabel *nameLable = [[UILabel alloc] init];
[self.contentView addSubview:nameLable];
nameLable.font = BJNameFont;
self.nameLable = nameLable;

// vip
UIImageView *vipImage = [[UIImageView alloc] init];
[self.contentView addSubview:vipImage];
vipImage.image = [UIImage imageNamed:@"vip"];
self.vipImage = vipImage;

// 正文
UILabel *contentLable = [[UILabel alloc] init];
[self.contentView addSubview:contentLable];
contentLable.font = BJContentFont;
contentLable.numberOfLines = 0;
self.contentLable = contentLable;

// 图片
UIImageView *photoImage = [[UIImageView alloc] init];
[self.contentView addSubview:photoImage];
self.photoImage = photoImage;

}
return self;
}


第二步 创建Status 和 StatusFrame 模型

Status的属性是和cell中控件对应的

//
//  WBStatus.h
//  WB
//
//  Created by hubaojie on 15-7-14.
//  Copyright (c) 2015年 hubaojie. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface WBStatus : NSObject
// 头像
@property(nonatomic,copy)NSString *icon;

// 昵称
@property(nonatomic,copy)NSString *name;

// vip
@property(nonatomic,assign)BOOL vip;

// 正文
@property(nonatomic,copy)NSString *content;

// 图片
@property(nonatomic,copy)NSString *photo;

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


StatusFrame中装各个控件的 frame 和 cellHeight

//
//  WBStatusFrame.h
//  WB
//
//  Created by hubaojie on 15-7-14.
//  Copyright (c) 2015年 hubaojie. All rights reserved.
//
#define BJNameFont [UIFont systemFontOfSize:14]
#define BJContentFont [UIFont systemFontOfSize:14]
#import <UIKit/UIKit.h>
#import "WBStatus.h"

@interface WBStatusFrame : NSObject
@property(nonatomic,strong)WBStatus *status;

// 头像
@property(nonatomic,assign,readonly)CGRect iconImageF;  //   控件的尺寸不允许别人随便更改,所以这里采取了readonly

// 昵称
@property(nonatomic,assign,readonly)CGRect nameLableF;

// vip
@property(nonatomic,assign,readonly)CGRect vipImageF;

// 正文
@property(nonatomic,assign,readonly)CGRect contentLableF;

// 图片
@property(nonatomic,assign,readonly)CGRect photoImageF;

// cellHeight
@property(nonatomic,assign,readonly)CGFloat cellHeight;   //  特别:设置cell高度
@end


第三步 重写setStatus 和 setStatusFrame 方法

重写setStatus,计算各控件 frame 和 cellHeight

//
//  WBStatusFrame.m
//  WB
//
//  Created by hubaojie on 15-7-14.
//  Copyright (c) 2015年 hubaojie. All rights reserved.
//

#import "WBStatusFrame.h"

@implementation WBStatusFrame
/**
*  重写setStatus方法,设置控件尺寸
*
*  @param status <#status description#>
*/
- (void)setStatus:(WBStatus *)status{
_status = status;

CGFloat padding = 10;

// 头像
CGFloat iconX = padding;
CGFloat iconY = padding;
CGFloat iconW = 30;
CGFloat iconH = 30;
_iconImageF = CGRectMake(iconX, iconY, iconW, iconH);

// 昵称
CGFloat nameX = CGRectGetMaxX(_iconImageF) + padding;
CGFloat nameH = [self.status.name sizeWithFont:BJNameFont].height;
CGFloat nameY = padding + (iconH - nameH) / 2;
CGFloat nameW = [self.status.name sizeWithFont:BJNameFont].width;
_nameLableF = CGRectMake(nameX, nameY, nameW, nameH);

// vip
CGFloat vipX = CGRectGetMaxX(_nameLableF) +padding;
CGFloat vipY = nameY;
CGFloat vipW = 14;
CGFloat vipH = 14;
_vipImageF = CGRectMake(vipX, vipY, vipW, vipH);

// 正文
CGFloat contentX = padding;
CGFloat contentY = CGRectGetMaxY(_vipImageF) + padding*2;
CGSize contentSize = [self.status.content boundingRectWithSize:CGSizeMake(300, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:BJContentFont} context:nil].size;
//    CGSize contentSize = [self.status.content sizeWithFont:BJContentFont];
_contentLableF = (CGRect){{contentX,contentY},contentSize};

// 图片
if(self.status.photo){
CGFloat photoX = padding;
CGFloat photoY = CGRectGetMaxY(_contentLableF) + padding*2;
CGFloat photoW = 100;
CGFloat photoH = 100;
_photoImageF = CGRectMake(photoX, photoY, photoW, photoH);

_cellHeight = CGRectGetMaxY(_photoImageF) + padding;
}else{
_cellHeight = CGRectGetMaxY(_contentLableF) + padding;
}

// cellHeight
}
@end


重写setStatusFrame方法,设置frame和data

//
//  WBStatusCell.h
//  WB
//
//  Created by hubaojie on 15-7-14.
//  Copyright (c) 2015年 hubaojie. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "WBStatusFrame.h"

@interface WBStatusCell : UITableViewCell
//
@property(nonatomic,strong)WBStatusFrame *statusFrame;

+ (instancetype)cellWithTableView:(UITableView *)tableView;
@end


- (void)setStatusFrame:(WBStatusFrame *)statusFrame{
_statusFrame = statusFrame;

// 设置数据
[self settingData];

// 设置尺寸
[self settingFrame];
}

/**
*  设置数据
*/
- (void)settingData{
WBStatus *status = self.statusFrame.status;

// 头像
self.iconImage.image = [UIImage imageNamed:status.icon];

// 昵称
self.nameLable.text = status.name;

// vip
if(status.vip){
self.nameLable.textColor = [UIColor redColor];                             //  在settingData中判断控件是否显示
self.vipImage.hidden = NO;
}else{
self.nameLable.textColor = [UIColor blackColor];
self.vipImage.hidden = YES;
}

// 正文
self.contentLable.text = status.content;

// 图片
if(status.photo)
self.photoImage.image = [UIImage imageNamed:status.photo];

}

/**
*  设置尺寸
*/
- (void)settingFrame{
// 头像
self.iconImage.frame = self.statusFrame.iconImageF;

// 昵称
self.nameLable.frame = self.statusFrame.nameLableF;

// vip
self.vipImage.frame = self.statusFrame.vipImageF;

// 正文
self.contentLable.frame = self.statusFrame.contentLableF;

// 图片
self.photoImage.frame = self.statusFrame.photoImageF;
}


第四步 获取Status数据,写数据源和代理方法

//
//  WBViewController.m
//  WB
//
//  Created by hubaojie on 15-7-14.
//  Copyright (c) 2015年 hubaojie. All rights reserved.
//

#import "WBViewController.h"
#import "WBStatus.h"
#import "WBStatusFrame.h"
#import "WBStatusCell.h"

@interface WBViewController ()
@property(nonatomic,strong)NSArray *statusFrames;
@end

@implementation WBViewController

- (NSArray *)statusFrames{
if(_statusFrames == nil){
NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];
NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
//        NSLog(@"%@",dictArray);
NSMutableArray *statusFrameArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
WBStatusFrame *statusFrame = [[WBStatusFrame alloc] init];
WBStatus *status = [WBStatus statusWithDict:dict];
statusFrame.status = status;                                                //  这一步关键:采用懒加载的方式设置statusFrame中的 数据 和 frame
[statusFrameArray addObject:statusFrame];
}
_statusFrames = statusFrameArray;
}
return _statusFrames;
}

- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.contentInset = UIEdgeInsetsMake(10, 0, 0, 0);
}

// 整个WBTableViewController相当于:我们
将33个双色球放到了大箱子中,用到第一个就取出第一个,用到第二个就取第二个。提高了性能,手机界面不会出现卡顿现象
#pragma mark - Table view data source 。。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.statusFrames.count;  // 采用懒加载的方式事先读取完数据
 }

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 1、创建cell
    WBStatusCell *cell = [WBStatusCell cellWithTableView:tableView];
//  2、设置cell数据
cell.statusFrame = self.statusFrames[indexPath.row];   // 用到哪个数据 就 调用哪个数据

//  3、返回cell
return cell;
}

// 设置cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
WBStatusFrame *statusFrame = self.statusFrames[indexPath.row];
return statusFrame.cellHeight;
}

// 点击cell做出的操作
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

// 选中后取消选中
 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];

}

@end







                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: