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