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

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

2014-12-04 16:15 706 查看
说明: 该部分完成对自定义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 : NSObject
12 /**
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  *  是否是vip
30  */
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 YYweiboModel
12
13 -(instancetype)initWithDict:(NSDictionary *)dict
14 {
15     if (self = [super init]) {
16         //使用KVC
17         [self setValuesForKeysWithDictionary:dict];
18     }
19     return self;
20 }
21
22 /**
23  *  工厂方法
24  *
25  *  @param dict 字典
26  *
27  *  @return 模型
28  */
29 +(instancetype)weiboModelWithDict:(NSDictionary *)dict
30 {
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 : UITableViewCell
13
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)settingData
100 {
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     }else
112     {
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  *  设置子控件的Frame
134  */
135 -(void)settingFrame
136 {
137     //1.设置头像的frame
138     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.设置微博昵称的frame
147     //昵称的X值=头像的最大的x值+padding
148     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图标的frame
155     //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.设置正文的frame
163     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.设置配图的frame
169     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)maxSize
191 {
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 @end
17
18 @implementation YYViewController
19
20 - (void)viewDidLoad
21 {
22     [super viewDidLoad];
23 }
24
25 #pragma mark -懒加载
26 -(NSArray *)weibos
27 {
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 *)tableView
46 {
47     return 1;
48 }
49 //每组多少行
50 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
51 {
52     return self.weibos.count;
53 }
54 //每组每行的数据-设置cell
55 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
56 {
57     //1.到缓存中去取cell
58     static NSString *ID=@"ID";
59      //2.没有则创建cell
60     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.返回cell
68     return cell;
69
70 }
71
72 #pragma mark-设置每一组的高度
73 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
74 {
75     //这里暂时给出一个高度,以后会做进一步的处理
76     return 200;
77 }
78 #pragma mark- 隐藏状态栏
79 -(BOOL)prefersStatusBarHidden
80 {
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 );

这里把计算过程封装在了下面的方法中:
/**
*  计算文本的宽高
*
*  @param str     需要计算的文本
*  @param font    文本显示的字体
*  @param maxSize 文本显示的范围
*
*  @return 文本占用的真实宽高
*/
- (CGSize)sizeWithString:(NSString *)str font:(UIFont *)font maxSize:(CGSize)maxSize
{
NSDictionary *dict = @{NSFontAttributeName : font};
// 如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围
// 如果将来计算的文字的范围小于指定的范围, 返回的就是真实的范围
CGSize size =  [str boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
return size;
}


iOS开发之旅之UIViewController解析

就iOS开发来说,UIViewController就最核心的类型之一。而iOS的整个UI开发的核心思想也是MVC的架构,从UIViewController的命名就可以看出它在MVC中所扮演的角色,那就是Controller啦。



Controller作为整个UI视图的控制器,对于用户的输入做出逻辑处理,例如用户点击某个按钮应该执行什么操作等;View角色只负责显示视图,view的这部分就是我们在nib或者storyboard设计的UI了。Model也就是我们的数据模型,例如从Core data中加载的实体类等等。这整个架构分工清晰,降低了代码的耦合度。今天我们要学习的角色就是Controller。

UIViewController与UIWindow、UIView的关系如下 图所示:



UIWindow在现实时会设置一个root controller,然后会将该root controller的root view设置为该window的root
view,root view又管理着整个视图的层次结构,这样就构建起了用户界面,并且相互之间耦合性较低。

按照官方的定义,View Controller为iOS提供了基础的视图管理模型,也就是它就是负责管理视图的,管理视图的层级、大小、内容、交互等。iOS的SDK中提供很多原生ViewController,以支持标准的用户界面,例如表视图控制器(UITableViewController)、导航控制器(UINavigationController)、标签栏控制器(UITabbarController)和iPad专有的UISplitViewController等。

按结构可以对iOS的所有ViewController分成两类:

1、主要用于展示内容的ViewController,这种ViewController主要用于为用户展示内容,并与用户交互,如UITableViewController,UIViewController。

2、用于控制和显示其他ViewController的ViewController。这种ViewController一般都是一个ViewController的容器,例如UINavigationController,UITabbarController,它们都有一个属性:viewControllers,将所有要管理的View
Controller添加到该数组就就行了,如图1。其中UINavigationController表示一种Stack式结构,push一个ViewController或pop一次,当前ViewController的导航栏上会显示上一个ViewController的Bar Button,点击该bar button可以返回上一个View Controller。而UITabbarController表示一个带有底部栏的视图控制器,底部栏按钮的个数就是ViewController的个数,各个ViewController是并列的,如图2。





图1 图2

UIViewController加载视图

UIViewController有两种加载方式,第一种是通过手动加载xib文件来加载视图,第二种是直接通过代码来创建View Controller中的师徒来加载。直接看示例吧。

方式一 :xib加载

在创建一个xib文件,将File's Owner设置为对应的UIViewController类型,然后关联File's Owner的view与xib中的root view(在创建UIViewController时自动创建了xib的话不需要这一步,只有分开创建时才需要手动建立关联,否则会报错。),然后通过如下代码即可创建:

[objc] view
plaincopy





// MainViewController *vc=[[MainViewController alloc]initWithNibName:@"MainViewController" bundle:nil];

// self.window.rootViewController = vc;

MainViewController *vc=[[MainViewController alloc] init];

self.window.rootViewController = vc;

方式二:代码添加View

思路就是将View添加到UIViewController的root view中,在UIViewController启动时默认会从与其关联的xib或者storyboard中加载视图,如果没有找到则root view为nil。我们可以覆写loadView方法,通过代码的形式向里面添加view。代码如下 :

[objc] view
plaincopy





[objc] view
plaincopy





// 加载视图时绘制

-(void) loadView

{

UILabel* label = [[UILabel alloc] initWithFrame:[UIScreen mainScreen].applicationFrame] ;

label.text = @"Draw The Text";

label.backgroundColor = [UIColor redColor] ;

self.view = label;

}

然后直接通过alloc和init创建UIVIewController即可。

UIViewController的生命周期

ViewController生命周期会经历初始化、加载视图、销毁视图、生命结束等过程。

1)init方法

初始化ViewController本身。

2)loadView方法

当view需要被展示而它却是nil时,viewController会调用该方法,如果代码构建View的话需要重写此方法。

3)viewDidLoad方法

执行完loadView后继续执行viewDidLoad,loadView时还没有view,而viewDidLoad时view已经创建好了。

4)viewDidUnload方法

当系统内存吃紧的时候会调用该方法。

5)dealloc

释放其他资源或内存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐