iOS 自定义cell(思路,以及详细步骤)

来源:互联网 发布:上知天文下肢瘫痪 编辑:程序博客网 时间:2024/05/21 17:26
通过代码自定义cell(cell的高度不一致)
1、新建一个继承自UITableView的类
2、重写initWithStyle:reuseIdentifier:方法
     1)添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中)
     2)  进行子控件一次性的属性设置(有些属性值需要设置一次,比如字体\固体的图片)

3、提供两个模型
 数据模型: 存放文字数据\图片数据
 frame模型: 存放数据模型\所有子控件的frame\cell的高度

4、cell拥有一个frame模型(不要直接拥有数据模型)

5、重写frame模型书信不过的setter方法:在这个方法中设置子控件的显示数据和frame

6、frame模型数据的初始化已经采取懒加载的方式 每一个cell对应的frame模型数据只加载一次

初始化子控件的时候 可能出现的控件都初始化

// 退出键盘  思路:让控制器所管理的UIView结束编辑

    [self.view endEditing:YES];



                             自定义cell

(1)使用系统提供给的单元格(加载数据)

1、查看要写的文件

2、写入pilst

3、通过 每样东西的键值对都是4个,用一个模型来描述

4、在Models建立一个XHLGoods模型

5、根据plist  向XHLGoods模型中添加属性(有几个就添加几个)

6、在XHLGoods.h 声明两个方法

- (instancetype) initWithDict:(NSDictionary *)dict;

+ (instancetype) goodsWithDict:(NSDictionary *)dict;


7、在XHLGoods.m  实现两个方法  模型写好之后懒加载数据

- (instancetype)initWithDict:(NSDictionary *)dict

{

    if (self = [super init]) {

        [self setValuesForKeysWithDictionary:dict];

    }

    return self;

}



+ (instancetype)goodsWithDict:(NSDictionary *)dict

{

    return [[self alloc] initWithDict:dict];

}


8、在XHLViewController.m 中懒加载数据 声明一个属性 用来保存模型中的数据

@property (nonatomic, strong) NSArray *goods;

#pragma marl -懒加载数据   重写get方法


- (NSArray *)goods

{

    if (_goods == nil) {

        //1、拿到Plist文件路径

        NSString *path = [[NSBundle mainBundle] pathForResource:@"Property List" ofType:nil];

        //2、接收最外一层大叔组(数组里面存的是字典)

        NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];

        //3、字典转模型

        NSMutableArray *arrayModels = [NSMutableArray array];

        //4、用字典遍历数组里面的字典

        for (NSDictionary *dict  in arrayDict) {

          //访问不到模型  导入模型。h

            XHLGoods *model = [XHLGoods goodsWithDict:dict];

            //模型全部加载到arrayModels

            [arrayModels addObject:model];

        }

        _goods = arrayModels;

    }

    return _goods;

}


9、创建TableView 实现 TableView数据源方法

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

   

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    //1、获取模型数据

    

    //2、创建单元格

    

    //3、把模型数据设置给单元格

    

    //4、返回单元格

}


#pragma mark  - 隐藏状态栏

- (BOOL)prefersStatusBarHidden

{

    return YES;

}


(2)自定义cell

10、自定义cell的两种实现方式

通过xib

1>当每个cell中的内容是固定的时候,控件个数、位置、尺寸等都一样的时候  可以使用xib加载

在Views里面创建一个名叫XHLGoodsCell的xib

通过自己写代码的方式来实现

2>每个Cell的结构不一样,每个Cell中的控件个数、样式都不一样的时候


8.通过xib方式实现自定义cell

8.1>创建一个XHLGoodsCell的xib文件


8.2>在xib中拖一个UITableViewCell,设置高度为80,宽度为屏幕宽度


8.3>向UITableViewCell中拖子控件

*拖一个UIImageView 到Cell中,设置里面的图片框的大小为 80 * 60  x=10, y= 10

*拖一个标题Label

*拖一个价格Label


//通过xib的方式来创建单元格  当我们创建单元格时,指定重用ID通过xib来指定

   XHLGoodsCell *cell = [[[NSBundle mainBundle] loadNibNamed:@"XHLGoodsCell" owner:nil options:nil] firstObject];


//3、把模型数据设置给单元格

    //在控制器中直接为cell的每个子控件赋值数据造成的问题

    //1、控制器强依赖于cell,一旦cell内部的子控件发生了变化,那么控制器的代码也得改(这就造成了紧耦合)

    //2cell的封装不够完整,凡是用到这个cell的地方,每次都要为cell的子控件一次赋值的语句,比如cell.xxx = model.title

    //3、解决办法:直接把模型传递给自定义cell,然后在自定义cell的内部解析model中的数据,赋值给自定义cell的子控件

   cell.goods = model;  //重写model中的setter方法

进入自定义cell重写goods的setter方法

- (void)setGoods:(XHLGoods *)goods

{

    _goods = goods;

    

    //把模型的数据设置给子控件

    self.imageViewIcon.image = [UIImage imageNamed:goods.icon];

    self.lblTitle.text = goods.title;

    self.lblPrice.text = [NSString stringWithFormat:@" %@",goods.price];

    self.lblBuyCount.text = [NSString stringWithFormat:@"%@ 人已选定”,goods.buyCount];  

    

}


在自定义cell中封装一个类方法

.h文件

+ (instancetype)goodsCellWithTableView:(UITableView *)tableView;


.m文件

+ (instancetype)goodsCellWithTableView:(UITableView *)tableView

{

    static NSString *ID = @"goods_cell";  //定义一个重用ID 根据重用ID取数据

    XHLGoodsCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];  //从缓存中区

    if (!cell) {

        cell = [[[NSBundle mainBundle] loadNibNamed:@"XHLGoodsCell" owner:nil options:nil] firstObject];

    }

    return cell;

}



 (3)实现加载更多

//系统的TableView.tableFooterView的特性   (x,y,w,h)   只能改变x,h  不能改变y,w

 //通过加载xib设置TableView.tableFooterView

    XHLFooterView *footView = [[[NSBundle mainBundle] loadNibNamed:@"XHLFooterView" owner:nil options:nil] firstObject];

    self.myTableView.tableFooterView = footView;


创建一个XHLFooterView.xib  里面放置一个button  

在button上添加一个View  在View添加两个指示器

最开始的时候让View隐藏

当点击button是  加载更多隐藏 view显示



XHLFooterView.m

/**

 *  加载更多按钮的单击事件

 *

 *

 */


- (IBAction)btnLoadMoreClick:(id)sender {

    

    //1、隐藏  加载更多 按钮

    self.btnLoadMore.hidden = YES;

    

    //2、显示  等待指示器  所在的哪个View

    self.waitingView.hidden = NO;

    

    //3、增加一条数据

    

    

    //4、刷新UITableView

}


等待指示器默认不旋转 设置它的属性Animating  默认不执行动画  Hides When Stopped停止就隐藏


XHLFooterView不能直接调用model数据 所以的使用代理  让控制器(ViewController)帮助它实现  


XHLFooterView.h


@class XHLFooterView;

@protocol XHLFooterViewDelegate <NSObject>


@required

- (void)footerViewUpdateData:(XHLFooterView *)footerView;


@end


@property (nonatomic, weak) id<XHLFooterViewDelegate> delegate;


XHLFooterView.m中

//调用代理方法实现下面的功能

    //调用footerViewUpdateData方法之前,为了保证调用不除错,所以的先判断代理对象是否实现了这个方法,如果实现了这个方法再调用,否则不调用

    if ([self.delegate respondsToSelector:@selector(footerViewUpdateData:)]) {

        //3、增加一条数据

        //31 创建一个模型对象

        //32 把模型对象加到控制器的goods集合当中

        //4、刷新UITableView

        

        [self.delegate footerViewUpdateData:self];

    }


然后再ViewController.m  是实现代理方法

#pragma mark -----XHLFooterView的代理方法

- (void)footerViewUpdateData:(XHLFooterView *)footerView

{

    //3、增加一条数据

    //31 创建一个模型对象

    XHLGoods *model = [[XHLGoods alloc]init];

    model.Title = @"红烧肉";

    model.Price = @"20";

    model.KanDian = @"国家SS景点";

    model.BackGroundImage = @"小明.jpg";


    //32 把模型对象加到控制器的goods集合当中

    [self.goods addObject:model];

    //4、刷新UITableView

    [self.myTableView reloadData];

    

}


4(实现加载更多2)

通过加载xib设置TableView.tableFooterView 的方法进行封装  降低耦合度,便于修改

XHLFooterView.h

+ (instancetype) footerView;


XHLFooterView.m

+ (instancetype)footerView

{

    XHLFooterView *footView = [[[NSBundle mainBundle] loadNibNamed:@"XHLFooterView" owner:nil options:nil] firstObject];

    return footView;

}


在ViewController里面 通过XHLFooterView的类方法进行调用 


XHLFooterView.m

//当这个方法被执行的时候表示XHLFooterView已经从xib中创建号了,那么意味着XHLFooterView中的子控件也被创建号,所以可以使用scrollView

- (void)awakeFromNib  //控件已经从xib中唤醒

{

    //在这里就表示 XHLFooterView  已经从xib中创建好了

    //self.scrollView.contentSize = ..;

    

}



3//根据label中文字的内容,来动态计算高和宽

 * 根据昵称的文字计算昵称label的宽和高

**影响昵称Label的高和宽的因素:字体大小、文字多少、高度取决于是否固定了宽度(是否显示了最大的宽度和高度)

**[字符串对象 boundingRectWithSize:CGSizeMake(MAXFKIAT,MAXFLOAT) options:NSStringDrawingUsesLineFragmentOriattributes:@{NSFontAttributeName:font} context:nil];

** 保证这里计算的时候使用的字体大小和创建Label时设置的字体大小一致,使用一个宏来统一设置

** 根据昵称Label的宽和高,计算x和y

4、计算good头像的 Frame

goodW = 15;

goodH = 15;


5 、 计算正文的Label的frame

* 封装一个根据字符串计算size的方法

- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize;

**注意  限制正文的宽度为355,然后  高度不限制

** 现在在viewDidLoad中暂时修改行高300,然后查看效果

** 设置Label中的文字可以换行(numberOfLines = 0 表示允许换行显示)



0 0
原创粉丝点击