1.创建九宫格的步骤列表
1.创建九宫格最开始要知道商品的宽和高,以及商品之间行的间距和列的间距,利用这四个数据就能会商品进行排序,主要代码如下
//定义列数和行数
NSUInteger col =3;
NSUInteger line = 2;
//定义商品的宽和高
NSUInteger shopWidth = 70;
NSUInteger shopHeight = 90;
//定义myView内的控件数为index
NSUInteger index = self.myView.subviews.count;
//计算商品的行间距和列间距
NSUInteger marginWidth = (self.myView.frame.size.width -col*shopWidth)/(col-1);
NSUInteger marginHeight = (self.myView.frame.size.height-line*shopHeight)/(line-1);
//利用frame排位置
UIImageView *myView = [[UIImageView alloc]init];
myView.frame = CGRectMake((index%col)*(shopWidth+marginWidth), (index/col)*(shopHeight+marginHeight), shopWidth, shopHeight);
2.创建一个类模型,类名为QYShop,类的属性个数和plist文件中字典的键值对的数量一致,同时重写init的构造方法和便利构造器,参数是NSDictionary.比如有两个属性的模型的声明如下
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *icon;
-(instancetype)initWithDict:(NSDictionary *)dict;
+(instancetype)shopWithDict:(NSDictionary *)dict;
2.1模型的实现如下
-(instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
self.icon = dict[@"icon"];
self.name = dict[@"name"];
}
return self;
}
+(instancetype)shopWithDict:(NSDictionary *)dict
{
return [[self alloc]initWithDict:dict];
}
3.模型建立好之后可以创建一个类型为NSArray的全局变量,重写这个属性的get方法达到懒加载的目的(每当使用到这个属性就把字典的内容加载保存到这个数组中来),代码实现如下
//懒加载数组字典数据
@property (nonatomic, strong) NSArray *myArray;
- (NSArray *)myArray
{
if (_myArray == nil) {
//创建一个可变数组添加字典数据
NSMutableArray *arrM =[NSMutableArray array];
NSString *file = [[NSBundle mainBundle]pathForResource:@"shops" ofType:@"plist"];
NSArray *arr = [NSArray arrayWithContentsOfFile:file];
for (NSDictionary *dict in arr) {
QYShop *shop =[QYShop shopWithDict:dict];
[arrM addObject:shop];
}
_myArray = arrM;
}
return _myArray;
}
4.做到第三步,我们就可以根据下标index从数组中取出字典,如果要使用字典,我们可以利用模型类QYShop创建一个实例对象myDict,将字典取出来保存到myDict这个实例对象中,然后通过myDict.icon和myDict.name就可以取到字典里这两个键对应的值,然后就利用父控件的长宽对图片和文字进行排列就能完成九宫格,利用父控件的长宽来定义图片和显示文字的frame的代码如下
CGFloat shopWidth = self.frame.size.width;
CGFloat shopHeight = self.frame.size.height;
_myImageView.frame = CGRectMake(0, 0, shopWidth, shopWidth);
_myLabel.frame = CGRectMake(0, shopWidth, shopWidth, shopHeight-shopWidth);
5.做完第4步后能实现的效果如图
6.虽然效果能实现了,但是我们最好自定义一个控件,即我们每次生成一个UIView的时候,UIView的内部都会自带一个UIImageview和一个UILabel,并且frame和UILabel的文字内容以及UIImageview的图片都已经设定好,要做好这一步,我们先要创建一个新类QYView,这个类必须是继承UIView的.
7.创建好Uiview后,给这个类添加两个属性,一个是UIImageView类型,一个是UILabel类型,这两个类型最好是隐蔽的,所以我们最好把这两个类型定义在类扩展里面,代码如下.
@interface QYView()
@property (nonatomic, weak) UIImageView *myImageView;
@property (nonatomic, weak) UILabel *myLabel;
@end
8.1一般自定义控件里面有三个方法,第一个方法是-(instancetype)initWithFrame:(CGRect)frame,即重构initWithFram方法,在这里之所以要重构initWithFrame这个方法是因为以后无论是以后调用init方法还是调用initWithFrame都会调用到我们的这个重构方法.
8.2我们在initWithFrame这个方法里要实现的内容就是生成一个UIImageview和一个UILabel,然后将这两个控件传给7定义的两个控件属性,重构的方法的代码如下
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
//创建UIImageView
UIImageView *myImageView1 = [[UIImageView alloc]init];
myImageView1.backgroundColor = [UIColor yellowColor];
[self addSubview:myImageView1];
_myImageView = myImageView1;
//创建UILabel
UILabel *myLabel1 = [[UILabel alloc]init];
myLabel1.backgroundColor = [UIColor blueColor];
[self addSubview:myLabel1];
_myLabel = myLabel1;
}
return self;
}
8.3接下来我们要实现第二个方法,即重写(void)layoutSubviews方法,在这个方法里,我们要做的是给我们7创建的两个控件属性的frame赋值(即管理这两个控件的布局),要注意的是调用这个方法必须要调用父类的[super layoutSubviews]方法,实现代码如下
//布局子控件
-(void)layoutSubviews{
[super layoutSubviews];
CGFloat shopWidth = self.frame.size.width;
CGFloat shopHeight = self.frame.size.height;
_myImageView.frame = CGRectMake(0, 0, shopWidth, shopWidth);
_myLabel.frame = CGRectMake(0, shopWidth, shopWidth, shopHeight-shopWidth);
}
8.4最后一个方法我们要做得是给7创建的2个控件属性设置内容(即要显示的真实数据),比如UIImageView的image图片内容和UILabel的文本内容,既然是设置这图片和文本,我们发现可以从QYShop这个模型类把数据取出来.要取到数据我们可以在自定义类QYView里设置一个类型为QYShop(模型类)的成员变量shops,然后重写它的set方法,在set方法里将shops的icon字段和name字段转换为图片和文字,保存到7创建的2个控件属性中,代码如下
//重写shops的set方法,在调用set方法的时候才加载数据
-(void)setShops:(QYShop *)shops
{
_shops =shops;
_myImageView.image = [UIImage imageNamed:shops.icon];
_myLabel.text = shops.name;
}
8.5总结:通过8.1到8.4我们发现自定义类里的三个方法都是用来修饰UIImageview和UILabel这两个属性的,这里我们就可以想象成UIImageview核UILabel这两个属性是一个人,这三个方法是这个人必不可少的成员变量,那么以后我们每自定义一个控件都要用这三个方法,就轻松的创建出我们的自定义控件了.
9.自定义好控件后以后我们做九宫格的添加按钮的代码就少了很多了,代码如下
- (IBAction)add {
//定义列数和行数
NSUInteger col =3;
NSUInteger line = 2;
//定义商品的宽和高
NSUInteger shopWidth = 70;
NSUInteger shopHeight = 90;
//定义myView内的控件数为index
NSUInteger index = self.myView.subviews.count;
//计算商品的行间距和列间距
NSUInteger marginWidth = (self.myView.frame.size.width -col*shopWidth)/(col-1);
NSUInteger marginHeight = (self.myView.frame.size.height-line*shopHeight)/(line-1);
//创建自定义控件
QYView *myView = [[QYView alloc]init];
//设置frame
myView.frame =CGRectMake((index%col)*(shopWidth+marginWidth), (index/col)*(shopHeight+marginHeight), shopWidth, shopHeight);
[self.myView addSubview:myView];
//调用Set方法将数据穿进去
myView.shops = self.myArray[index];
// QYView *myView = [[QYView alloc]initWithFrame:CGRectMake((index%col)*(shopWidth+marginWidth), (index/col)*(shopHeight+marginHeight), shopWidth, shopHeight)];
//控制添加和删除按钮的可用性
self.addBtn.enabled = index!=(col*line-1);
self.removeBtn.enabled=YES;
}
10.分析以上添加按钮的代码,我们发现
//创建自定义控件
QYView *myView = [[QYView alloc]init];
这里会调用到我们的8.2的initWithFrame方法
10.1然后
//设置frame
myView.frame =CGRectMake((index%col)*(shopWidth+marginWidth), (index/col)*(shopHeight+marginHeight), shopWidth, shopHeight);
这里会调用我们8.3的(void)layoutSubviews方法
10.2
//调用Set方法将数据穿进去
myView.shops = self.myArray[index];
等号的左边会调用我么的8.4的set方法,等号右边调用我们的懒加载方法,因此我们写的懒加载,自定义控件的三个方法通过3行代码就可完成,控制器管得东西就少了很多.