第二十四篇:缩合练习代码---简单微博(自定义Cell)

1.效果图:


2.写出的详细步骤:

(1)向Main.storyboard里的控制器中添加一个UITableView控件。

(2)ViewController类遵守两个协议(UITableViewDataSource , UITableViewDelegate),并使tableView属性与UITableView控件连线,设置当前控制器成为tableView的数据源对象和代理对象,实现以下方法:

#pragma mark - 数据源方法

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

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

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

(3)发现没有数据,那么需要字典转模型;数据模型:QJStatuse;信息模型:QJStatuseFrame。

 》QJStatuse:只有五个属性值对应字典的每个Key。

 》QJStatuseFrame:拥有一个QJStatuse对象(即数据)和每个数据控件的frame。提高性能。

问题:自写一个 计算文字的frame方法:

/** 返回文字真实的Size */
- (CGSize) sizeWithText:(NSString *)text Size:(CGSize)size font:(UIFont *)font{
    
    NSDictionary * attrib = @{NSFontAttributeName : font};
    return [text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrib context:nil].size;
}
(4)并发现每个Cell是不一样的,所以需要用代码自定义一个UITableViewCell -->QJStatuseCell继承UITableViewCell。那么QJSatuseCell类必须要提够一些方法,使上面数据源协议的第三个方法可以实现:

 》重写- initWithStyle: reuseIdentifier: 对象方法,用于添加控件。

 》创建一个QJSatuseCell方法, 并调用重写上述方法向QJSatuseCell对象.contentView中添加五个不同的控件(iconImgView,nameLable,vipImgView,text1Lable,pictureImgView),但不设置任何数据,因为该方法只用来创建Cell对象。

  》写出该对象属性_statuseFrame的 setter,用于:根据传入的statuseFrame参数 初始化每个对应Cell内五个控件的:1.内容 2.设置frame

(5)最后每个Cell的高度不一要,那么只要实现代理协议中的一个方法:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    QJStatuseFrame * sta = self.statuseFrames[indexPath.row];
    return sta.cellHeight;
}


3.完整代码:

Model:

//
//  QJStatuse.h
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//

#import <UIKit/UIKit.h>

@interface QJStatuse : NSObject

@property (nonatomic,copy)NSString * icon;
@property (nonatomic,copy)NSString * name;
@property (nonatomic,copy)NSString * text;
@property (nonatomic,copy)NSString * picture;
@property (nonatomic,assign)NSNumber * vip;


+ (instancetype)statuseWithDictionary:(NSDictionary *)dic;
- (instancetype)initWithDictionary:(NSDictionary *)dic;

@end

//
//  QJStatuse.m
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

#import "QJStatuse.h"

@implementation QJStatuse

+ (instancetype)statuseWithDictionary:(NSDictionary *)dic{
    return [[self alloc]initWithDictionary:dic];
}
- (instancetype)initWithDictionary:(NSDictionary *)dic{
    if (self = [super init]) {
        self.icon = dic[@"icon"];
        self.name = dic[@"name"];
        self.text = dic[@"text"];
        self.picture = dic[@"picture"];
        self.vip = dic[@"vip"];
    }
    return self;
}

@end


//
//  QJStatusFrame.h
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class QJStatuse;

@interface QJStatuseFrame : NSObject

@property (nonatomic, strong) QJStatuse *statuse;

/**
 *  头像的frame
 */
@property (nonatomic, assign, readonly) CGRect iconFrame;
/**
 *  昵称的frame
 */
@property (nonatomic, assign, readonly) CGRect nameFrame;
/**
 *  会员图标的frame
 */
@property (nonatomic, assign, readonly) CGRect vipFrame;
/**
 *  正文的frame
 */
@property (nonatomic, assign, readonly) CGRect textFrame;
/**
 *  配图的frame
 */
@property (nonatomic, assign, readonly) CGRect pictureFrame;

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

@end
//
//  QJStatuseFrame.m
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
// 每个QJStatuseFrame对象都拥有 每个控件的 信息 和 frame

#import "QJStatuseFrame.h"
#import "QJStatuse.h"

#define nameFont [UIFont systemFontOfSize:14]
#define textFont [UIFont systemFontOfSize:16]

@implementation QJStatuseFrame

/** 属性_statuse的setter方法 */
- (void)setStatuse:(QJStatuse *)statuse{
    
    //每个控件的信息
    _statuse = statuse ;
    
    //间隔
    CGFloat padding = 10 ;
    
    //iconFrame
    CGFloat iconX = padding ;
    CGFloat iconY = padding ;
    CGFloat iconW = 50;
    CGFloat iconH = 50;
    _iconFrame = CGRectMake(iconX, iconY, iconW, iconH);
    
    //nameFrame
    CGSize nameSize = [self sizeWithText:self.statuse.name Size:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) font:nameFont];
    CGFloat nameX = CGRectGetMaxX(self.iconFrame) + padding;
    CGFloat nameY = self.iconFrame.origin.y + (self.iconFrame.size.height - nameSize.height)*0.5;
    _nameFrame = CGRectMake(nameX, nameY, nameSize.width, nameSize.height);
    
    //vipFrame
    CGFloat vipX = CGRectGetMaxX(self.nameFrame) + padding;
    CGFloat vipY = self.nameFrame.origin.y ;
    CGFloat vipW = 14;
    CGFloat vipH = 14;
    _vipFrame = CGRectMake(vipX, vipY, vipW, vipH);
    
    //正文textFrame
    CGFloat textX = padding ;
    CGFloat textY = CGRectGetMaxY(self.iconFrame) + padding;
    CGSize textSize = [self sizeWithText:self.statuse.text Size:CGSizeMake(394, CGFLOAT_MAX) font:textFont];
    _textFrame = CGRectMake(textX, textY, textSize.width, textSize.height);
    
    //符加图pictureFrame
    if (self.statuse.picture ) {
        CGFloat pictureX = padding ;
        CGFloat pictureY = CGRectGetMaxY(self.textFrame);
        CGFloat pictureW = 100;
        CGFloat pictureH = 100;
        _pictureFrame = CGRectMake(pictureX, pictureY, pictureW, pictureH);
        
        _cellHeight = CGRectGetMaxY(self.pictureFrame) + padding;
    }
    else{
        _pictureFrame = CGRectZero ;
        _cellHeight = CGRectGetMaxY(self.textFrame) + padding;
    }
}
/** 返回文字真实的Size */
- (CGSize) sizeWithText:(NSString *)text Size:(CGSize)size font:(UIFont *)font{
    
    NSDictionary * attrib = @{NSFontAttributeName : font};
    return [text boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attrib context:nil].size;
}

@end


View:
//
//  QJStatuseCell.h
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>
@class QJStatuseFrame;

@interface QJStatuseCell : UITableViewCell

@property (nonatomic , weak)QJStatuseFrame * statuseFrame;

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

@end
//
//  QJStatuseCell.m
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

#import "QJStatuseCell.h"
#import "QJStatuseFrame.h"
#import "QJStatuse.h"

#define nameFont [UIFont systemFontOfSize:14]
#define textFont [UIFont systemFontOfSize:16]

@interface QJStatuseCell ()

@property (nonatomic , weak)UIImageView * iconImgView ;
@property (nonatomic , weak)UILabel * nameLable ;
@property (nonatomic , weak)UIImageView * vipImgView ;
@property (nonatomic , weak)UILabel * text1Lable ;
@property (nonatomic , weak)UIImageView * pictureImgView ;

@end

@implementation QJStatuseCell

+ (instancetype)statuseCellWithTableView:(UITableView *)tableView{
    // 可重用的标识符
    NSString * ID = @"statuseCell";
    QJStatuseCell * cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        cell = [[self alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

/** 重写从父类继承的对象方法:只添加控件,不设置任何数据,因为数据是不确定的 */
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        //添加头象
        UIImageView * iconImgView = [[UIImageView alloc]init];
        [self.contentView addSubview:iconImgView];
        self.iconImgView = iconImgView;
        
        //添加nameLable
        UILabel * nameLable = [[UILabel alloc]init];
        nameLable.font = nameFont;
        [self.contentView addSubview:nameLable];
        self.nameLable = nameLable;
        
        //添加vipImgView
        UIImageView * vipImgView = [[UIImageView alloc]init];
        [self.contentView addSubview:vipImgView];
        self.vipImgView = vipImgView;
        
        //添加text1Lable
        UILabel * textLalbe = [[UILabel alloc]init];
        textLalbe.font = textFont ;
        textLalbe.numberOfLines = 0; // 不限制行数,自动换行
        [self.contentView addSubview:textLalbe];
        self.text1Lable = textLalbe ;
        
        
        //添加pictureImgView
        UIImageView * pictureImgView = [[UIImageView alloc]init];
        [self.contentView addSubview:pictureImgView];
        self.pictureImgView = pictureImgView ;
    }
    return self ;
}

/**
 *   初始化每个对应Cell内五个控件的:1.内容 2.设置frame
 */
- (void)setStatuseFrame:(QJStatuseFrame *)statuseFrame{
    
    _statuseFrame = statuseFrame;
    
    // 初始化头象
    self.iconImgView.image = [UIImage imageNamed:statuseFrame.statuse.icon];
    self.iconImgView.frame = statuseFrame.iconFrame;
    
    // 初始化nameLable
    self.nameLable.text = statuseFrame.statuse.name;
    self.nameLable.frame = statuseFrame.nameFrame;
    
    // 初始化vipImgView
    if ([statuseFrame.statuse.vip intValue]) {
        self.nameLable.textColor = [UIColor redColor];
        self.vipImgView.hidden = NO;
        self.vipImgView.image = [UIImage imageNamed:@"vip"];
        self.vipImgView.frame = statuseFrame.vipFrame;
    }
    else{
        self.nameLable.textColor = [UIColor blackColor];
        self.vipImgView.hidden = YES ;
    }
    
    // 初始化textLable
    self.text1Lable.text = statuseFrame.statuse.text;
    self.text1Lable.frame = statuseFrame.textFrame;
    
    // 初始化pictureImgView,
    // 无需判断是否需要隐藏,因为如果没有图,那么pictureFrame = CGRectZero
    self.pictureImgView.image = [UIImage imageNamed:statuseFrame.statuse.picture];
    self.pictureImgView.frame = statuseFrame.pictureFrame;
    
}

//- (void)awakeFromNib {
//    // Initialization code
//}
//
//- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
//    [super setSelected:selected animated:animated];
//
//    // Configure the view for the selected state
//}

@end

Controller:

//
//  ViewController.h
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end
//
//  ViewController.m
//  09-自定义cell-微博
//
//  Created by 瞿杰 on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

#import "ViewController.h"
#import "QJStatuse.h"
#import "QJStatuseFrame.h"
#import "QJStatuseCell.h"

@interface ViewController ()<UITableViewDataSource , UITableViewDelegate>

@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (strong,nonatomic)NSArray * statuseFrames;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 设置数据源
    self.tableView.dataSource = self;
    self.tableView.delegate = self ;
}

- (BOOL)prefersStatusBarHidden{
    return YES;
}

- (NSArray *)statuseFrames{
    if (_statuseFrames == nil) {
        NSString * path = [[NSBundle mainBundle]pathForResource:@"statuses.plist" ofType:nil];
        NSArray * statuArray = [NSArray arrayWithContentsOfFile:path];
        NSMutableArray * statuseFrames = [NSMutableArray array];
        for(NSDictionary * dic in statuArray){
            QJStatuse * stat = [QJStatuse statuseWithDictionary:dic];
            QJStatuseFrame * statFrame = [[QJStatuseFrame alloc]init];
            statFrame.statuse = stat ;
            [statuseFrames addObject:statFrame];
        }
        _statuseFrames = statuseFrames;
    }
    return _statuseFrames;
}

#pragma mark - 数据源方法

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.statuseFrames.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 创建一个cell
    QJStatuseCell * cell = [QJStatuseCell statuseCellWithTableView:tableView];
    
    //初始化内容
    cell.statuseFrame = self.statuseFrames[indexPath.row];
    
    return cell;
}

#pragma mark - 代理方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    QJStatuseFrame * sta = self.statuseFrames[indexPath.row];
    return sta.cellHeight;
}

@end





你可能感兴趣的:(ios,Objective-C,UITableView)