IOS九宫格设计(含字典转模型,自定义控件)

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行代码就可完成,控制器管得东西就少了很多.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值