首页 > 代码库 > iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)

iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)

iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)

说明:该部分完成对自定义cell页面的基本搭建,尚未进行优化处理。且还存在很多问题,譬如每行的高度设置暂时是固定的,这些问题将会在下一篇文中解决。

一、实现效果

           

二、实现代码

数据模型部分:

YYweiboModel.h文件

 1 // 2 //  YYweiboModel.h 3 //  微博基本信息展示 4 // 5 //  Created by 孔医己 on 14-6-2. 6 //  Copyright (c) 2014年 itcast. All rights reserved. 7 // 8  9 #import <Foundation/Foundation.h>10 11 @interface YYweiboModel : NSObject12 /**13  *  昵称14  */15 @property(nonatomic,copy)NSString *name;16 /**17  *  正文18  */19 @property(nonatomic,copy)NSString *text;20 /**21  *  头像22  */23 @property(nonatomic,copy)NSString *icon;24 /**25  *  配图26  */27 @property(nonatomic,copy)NSString *picture;28 /**29  *  是否是vip30  */31 @property(nonatomic,assign)BOOL vip;32 33 //接口34 -(instancetype)initWithDict:(NSDictionary *)dict;35 +(instancetype)weiboModelWithDict:(NSDictionary *)dict;36 @end

YYweiboModel.m文件

 1 // 2 //  YYweiboModel.m 3 //  微博基本信息展示 4 // 5 //  Created by 孔医己 on 14-6-2. 6 //  Copyright (c) 2014年 itcast. All rights reserved. 7 // 8  9 #import "YYweiboModel.h"10 11 @implementation YYweiboModel12 13 -(instancetype)initWithDict:(NSDictionary *)dict14 {15     if (self = [super init]) {16         //使用KVC17         [self setValuesForKeysWithDictionary:dict];18     }19     return self;20 }21 22 /**23  *  工厂方法24  *25  *  @param dict 字典26  *27  *  @return 模型28  */29 +(instancetype)weiboModelWithDict:(NSDictionary *)dict30 {31     return [[self alloc]initWithDict:dict];32 }33 @end

视图部分:

YYweiboCell.h文件

 1 // 2 //  YYweiboCell.h 3 //  微博基本信息展示 4 // 5 //  Created by 孔医己 on 14-6-2. 6 //  Copyright (c) 2014年 itcast. All rights reserved. 7 // 8  9 #import <UIKit/UIKit.h>10 11 @class YYweiboModel;12 @interface YYweiboCell : UITableViewCell13 14 15 @property(nonatomic,strong)YYweiboModel *weibo;16 @end

YYweiboCell.m文件

  1 //  2 //  YYweiboCell.m  3 //  微博基本信息展示  4 //  5 //  Created by 孔医己 on 14-6-2.  6 //  Copyright (c) 2014年 itcast. All rights reserved.  7 //  8   9 #import "YYweiboCell.h" 10 #import "YYweiboModel.h" 11  12 #define YYNameFont [UIFont systemFontOfSize:15] 13 #define YYTextFont [UIFont systemFontOfSize:16] 14  15 @interface YYweiboCell() 16 /** 17  *  头像 18  */ 19 @property(nonatomic,weak)UIImageView *iconView; 20 /** 21  *  vip图标 22  */ 23 @property(nonatomic,weak)UIImageView *vipView; 24 /** 25  *  微博昵称 26  */ 27 @property(nonatomic,weak)UILabel *nameLabel; 28 /** 29  *  配图 30  */ 31 @property(nonatomic,weak)UIImageView *pictureView; 32 /** 33  *  正文 34  */ 35 @property(nonatomic,weak)UILabel *textLab; 36  37 @end 38  39 @implementation YYweiboCell 40  41 //重写构造方法,让自定义的cell一创建出来就有五个子控件 42 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 43 { 44     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 45     if (self) { 46         //1.添加头像 47         UIImageView *img=[[UIImageView alloc]init]; 48         [self.contentView addSubview:img]; 49         self.iconView=img; 50          51         //2.添加昵称 52         UILabel *namelab=[[UILabel alloc]init]; 53         //在创建昵称的时候就要告诉它,将来要用15号字体显示 54         namelab.font=YYNameFont; 55         [self.contentView addSubview:namelab]; 56         self.nameLabel=namelab; 57          58         //3.vip 59         UIImageView  *vipview=[[UIImageView alloc]init]; 60         vipview.image=[UIImage imageNamed:@"vip"]; 61         [self.contentView addSubview:vipview]; 62         self.vipView=vipview; 63       64         //4.正文 65         UILabel *textlab=[[UILabel alloc]init]; 66         //在创建正文的时候就要告诉它,将来要用16号字体显示 67         textlab.font=YYTextFont; 68         //设置正文在进行显示的时候进行换行 69         textlab.numberOfLines=0; 70         [self.contentView addSubview:textlab]; 71         self.textLab=textlab; 72          73         //5.图片 74         UIImageView *picture=[[UIImageView alloc]init]; 75         [self.contentView addSubview:picture]; 76         self.pictureView=picture; 77     } 78     return self; 79 } 80  81 /** 82  *  重写set方法 83  * 84  *  @param weibo 微博 85  */ 86 -(void)setWeibo:(YYweiboModel *)weibo 87 { 88     //不要忘了,记录传递进来的模型 89     _weibo=weibo; 90     //给子控件赋值数据 91     [self settingData]; 92     //设置子控件的frame 93     [self settingFrame]; 94 } 95  96 /** 97  *  对子控件的数据进行设置 98  */ 99 -(void)settingData100 {101     //1.设置头像的数据102     self.iconView.image=[UIImage imageNamed:_weibo.icon];103     104     //2.设置vip图标的数据105     //判断是否是vip,如果是那么就显示图标,并把字体设置为红色106     //注意这里的判断107     if (_weibo.vip) {108         self.vipView.hidden=NO;109 //        [self.textLab setTintColor:[UIColor redColor]];110         self.nameLabel.textColor=[UIColor redColor];111     }else112     {113         self.vipView.hidden=YES;114         self.nameLabel.textColor=[UIColor blackColor];115     }116 117     118     //所以的vip图标都是一样的,没有必要每次都设置,只需要在构造方法中设置一次就可以了。119    // self.vipView.image=[UIImage imageNamed:@"vip"];120     121     //3.设置正文内容的数据122     self.textLab.text=_weibo.text;123     124     //4.设置配图的数据125     self.pictureView.image=[UIImage imageNamed:_weibo.picture];126     127     //5.设置微博昵称数据128     self.nameLabel.text=_weibo.name;129 }130 131 132 /**133  *  设置子控件的Frame134  */135 -(void)settingFrame136 {137     //1.设置头像的frame138     CGFloat padding=10;139     CGFloat iconViewX=padding;140     CGFloat iconViewY=padding;141     CGFloat iconViewW=30;142     CGFloat iconViewH=30;143     144     self.iconView.frame=CGRectMake(iconViewX, iconViewY, iconViewW, iconViewH);145     146     //2.设置微博昵称的frame147     //昵称的X值=头像的最大的x值+padding148     CGFloat nameLabelX=CGRectGetMaxX(self.iconView.frame)+padding;149     CGSize nameSize=[self sizeWithString:_weibo.name font:YYNameFont maxSize:CGSizeMake(MAXFLOAT,MAXFLOAT)];150     //昵称的Y值=(头像高度-整个文本字体的高度)*0.5+头像的Y值151     CGFloat nameLableY=(iconViewH-nameSize.height)*0.5+iconViewY;152     self.nameLabel.frame=CGRectMake(nameLabelX, nameLableY, nameSize.width, nameSize.height);153     154     //3.设置vip图标的frame155     //vip图标的x值=昵称的最大x值+间隙156     CGFloat vipX=CGRectGetMaxX(self.nameLabel.frame)+padding;157     CGFloat vipY=nameLableY;158     CGFloat vipW=14;159     CGFloat vipH=14;160     self.vipView.frame=CGRectMake(vipX, vipY, vipW, vipH);161     162     //4.设置正文的frame163     CGFloat textLabX=iconViewX;164     CGFloat textLabY=CGRectGetMaxY(self.iconView.frame)+padding;165     CGSize textSize=[self sizeWithString:_weibo.text font:YYTextFont maxSize:CGSizeMake(300,MAXFLOAT)];166     self.textLab.frame=CGRectMake(textLabX, textLabY, textSize.width, textSize.height);167     168     //5.设置配图的frame169     if (_weibo.picture) {170         CGFloat pictureX=iconViewX;171         CGFloat pictureY=CGRectGetMaxY(self.textLab.frame)+padding;172         CGFloat pictureW=100;173         CGFloat pictureH=100;174         self.pictureView.frame=CGRectMake(pictureX, pictureY, pictureW, pictureH);175     }176    177 #warning 未完成178 }179 180 181 /**182  *  计算文本的宽高183  *184  *  @param str     需要计算的文本185  *  @param font    文本显示的字体186  *  @param maxSize 文本显示的范围187  *188  *  @return 文本占用的真实宽高189  */190 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize191 {192     NSDictionary *dict = @{NSFontAttributeName : font};193     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围194     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围195     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;196     return size;197 }198 @end

主控制器部分:

YYViewController.m文件

 1 // 2 //  YYViewController.m 3 //  微博基本信息展示 4 // 5 //  Created by 孔医己 on 14-6-2. 6 //  Copyright (c) 2014年 itcast. All rights reserved. 7 // 8  9 #import "YYViewController.h"10 #import "YYweiboModel.h"11 #import "YYweiboCell.h"12 13 @interface YYViewController ()14 @property(nonatomic,strong)NSArray *weibos;15 16 @end17 18 @implementation YYViewController19 20 - (void)viewDidLoad21 {22     [super viewDidLoad];23 }24 25 #pragma mark -懒加载26 -(NSArray *)weibos27 {28     if (_weibos==Nil) {29         NSString *fullpath=[[NSBundle mainBundle]pathForResource:@"statuses.plist" ofType:nil];30         NSArray *arrayM=[NSArray arrayWithContentsOfFile:fullpath];31         32         NSMutableArray *models=[NSMutableArray arrayWithCapacity:arrayM.count];33         for (NSDictionary *dict in arrayM) {34             YYweiboModel *weibomodel=[YYweiboModel weiboModelWithDict:dict];35             [models addObject:weibomodel];36         }37         _weibos=[models copy];38     }39     return _weibos;40 }41 42 #pragma mark- 数据源方法43 //返回多少组44 //这里可以不写,默认返回一组45 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView46 {47     return 1;48 }49 //每组多少行50 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section51 {52     return self.weibos.count;53 }54 //每组每行的数据-设置cell55 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath56 {57     //1.到缓存中去取cell58     static NSString *ID=@"ID";59      //2.没有则创建cell60     YYweiboCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];61     if (cell==nil) {62         cell=[[YYweiboCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];63     }64    65     //3.设置cell的数据66     cell.weibo=self.weibos[indexPath.row];67     //4.返回cell68     return cell;69     70 }71 72 #pragma mark-设置每一组的高度73 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath74 {75     //这里暂时给出一个高度,以后会做进一步的处理76     return 200;77 }78 #pragma mark- 隐藏状态栏79 -(BOOL)prefersStatusBarHidden80 {81     return YES;82 }83 @end

三、实现思路整理

设置frame时的思路和一些注意点:
(1)
一个控件没有frame肯定显示不出来
设置frame的过程中需要从哪里入手呢?以后遇到要为很多控件设置frmae的时候。建议先找控件之间的关系,先找准一个固定不变的点,然后再计算不确定的控件的frmae.总要有一个点,再来计算其他的东西。
在这个应用中找到规律,先设置头像的,再设置其他的。
在真实开发中间隙等是由美工提供的。计算x,y,w,h等得值。分别计算所有控件的frame,注意这是依赖于数据的。
 
(2)
获取控件的最大值CGRectMaxX(SELF.ICONvIEW.FRAME)或取头像最大的x值。
在ios7中计算文字的宽度和高度?
需要传递一个字体。影响文本的宽度和高度的因素:(1)字体的大小;(2)存放文本的最大的范围。在计算文本的宽高时,应该告诉这两个。
_weibo.name sizewithFont:nil    ios7以前的方法
ios7以后要传4个参数
boundingRectWthSize:(cgsize).....将来能够显示文本的范围,宽和高。
nsdictionary  *dict=@{NSfontattributename:宏}
在创建昵称的时候就要告诉它,将来以15号的字体显示。(注意不要忘了这一点,否则计算出来的不准确)
不限制其宽度和高度的大小:MAXFLOAT
计算文本的宽高,把这个功能封装。接受三个参数,字符串,字体,Maxsize.返回值为CGSIZE.
需要计算的文本
文本显示的字体
文本显示的范围
文本占用的真实宽高。
注意:有关字体的计算,在创建的时候就要指定其将要显示的字号是多大。
内容文本的宽高和昵称不一样,正文会换行,那么就限制一下其宽度,不限制高度就可以了。
cell的高度不够,需要在viewdioad中设置cell的高度(大失所望)
默认label只显示一行。当创建正文的时候,还要设置让其自定换行。设置为0
 
 (3)
如果没有配图的话就不计算它的宽高,把计算的过程放到if大括号里边。
设置配图的问题:有的又配图,有的没有配图(cell滚动离开视野放到缓存池中)。问题在于,如果需要一个没有配图的,这时候去缓存中去取,取到的是一个有配图的那不是就冲突了么?
如何解决这个问题:
在设置数据的时候进行判断,如果有配图,那么就设置数据,.hidden=no;
如果没有配图的话那就不让它显示。hidden=YES.
注意点:在tableview中有一个复用的问题,有显示就要有隐藏。这是一个陷阱。一定要记住。
 
 (4)
所有的vip图标都是同一个,可以在init初始化方法中对vip图标进行设置。
此时出现了一个新的问题。所有的宽高计算一次就可以了,但是这里每次滚动都会调用计算,没有必要。
 
四、重要说明
 
IOS7以后计算文本的宽度和高度:

    //4.设置正文的frame

    CGFloat textLabX=iconViewX;

    CGFloat textLabY=CGRectGetMaxY(self.iconView.frame)+padding;

    CGSize textSize=[self sizeWithString:_weibo.text font:YYTextFont maxSize:CGSizeMake(300,MAXFLOAT)];

    self.textLab.frame=CGRectMake(textLabX, textLabY, textSize.width, textSize.height);

    这里把计算过程封装在了下面的方法中:

 1 /** 2  *  计算文本的宽高 3  * 4  *  @param str     需要计算的文本 5  *  @param font    文本显示的字体 6  *  @param maxSize 文本显示的范围 7  * 8  *  @return 文本占用的真实宽高 9  */10 - (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize11 {12     NSDictionary *dict = @{NSFontAttributeName : font};13     // 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围14     // 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围15     CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;16     return size;17 }

 

iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)