初衷和项目源代码
主要是解决:同一份数据,可以动态切换不同的布局
。如果模型数据很多条,那么就肯定用UITtableview
。
原理
-
MyGirdeLayout->栅格布局:
树形结构
-
UIView.subviews->子视图:
平面结构
-
栅格布局:
- 将一个矩形的视图区域按行或者按列的方式划分为
多个子区域
,子区域根据布局的要求可以继续递归划分
。栅格布局里面的子视图
将按照添加的顺序依次填充到对应的叶子区域中去的布局方式
。 - 通过
一套自定义的布局体系来划分位置和尺寸
,添加到栅格布局里面的子视图将不再需要指定位置和尺寸
而是由栅格布局中的子栅格来完成
,因此可以很很方便的调整布局结构,从而实现动态布局的能力。 所谓栅格其实就是一个矩形区域
,我们知道一个视图其实就是一个矩形区域,而子视图的frame属性其实就是父视图中的某个特定的子区域部分
。 - 既然子视图最终占据的是父视图的某个子矩形区域。那么我们也可以先将
一个矩形区域按照某种规则分解为多个子矩形区域
,然后再将子视图填充到对应的子矩形区域中去
,这就是栅格布局的实现思想
。
叶子格子和非叶子格子区别
-
叶子格子
表示里面没有子格子而非叶子格子
表示里面有子格子 -
非叶子栅格
只能设置一个方向的停靠,具体只能设置左中右或者上中下 -
叶子栅格
如果设置了gravity则填充的子视图必须要设置明确的尺寸
视图组
- 原理
-
数据
{"size":"fill","cols":[{"size":"50%","padding":"{0,5,0,5}","right- borderline":{"head":1,"tail":1,"offset":1,"thick"1,"color":"#EEEEEE"}, "bottom-borderline":{"head":1,"tail":1,"offset":1,"thick":1, "color":"#EEEEEE"},"tag":1003,"action":"handleTap:","rows": [{"size":"fill","cols":[{"size":"fill","rows":[{"size":"wrap"}, {"size":"wrap"},{"padding":"{5, 5, 5, 5}","size":"wrap"}]}, {"padding":"{5, 5, 5, 5}","size":"fill"}]}]}
-
视图
NSMutableArray *temp = [NSMutableArray array]; UIImageView *backgroudImageView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"bk1"]]; [temp addObject:backgroudImageView]; UILabel *titleLabel = [UILabel new]; titleLabel.text = @"南京精选"; titleLabel.font = [CFTool font:13]; titleLabel.textColor = UIColor.whiteColor; titleLabel.textAlignment = NSTextAlignmentCenter; titleLabel.adjustsFontSizeToFitWidth = YES; [temp addObject:titleLabel]; UILabel *subTitleLabel = [UILabel new]; subTitleLabel.text = @"天猫超市"; subTitleLabel.font = [CFTool font:11]; subTitleLabel.textColor = UIColor.whiteColor; subTitleLabel.textAlignment = NSTextAlignmentCenter; subTitleLabel.adjustsFontSizeToFitWidth = YES; [temp addObject:subTitleLabel]; NSArray *titles = @[@"周末疯狂趴",@"送5升菜籽油"]; for (NSString *title in titles) { UILabel *lb = [UILabel new]; lb.text = title; lb.font = [CFTool font:12]; lb.textColor = UIColor.redColor; lb.adjustsFontSizeToFitWidth = YES; [temp addObject:lb]; } NSArray *imageNames = @[@"p1-31",@"p1-32"]; for (NSString *imageName in imageNames) { UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]]; [temp addObject:imageView]; } UIImageView *optionalView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"p1-12"]]; [temp addObject:optionalView]; [self.rootLayout addViewGroup:temp withActionData:@"aa" to:sPartTag3];
-
这样就可以根据数据的
Tag
来指定标签内才会放置绑定的视图组
。
布局技巧
拆分子格子几种方法
描述
MyGridLayout_Demo1.png- 把格子拆分为2个行子格子,然后第2个行子格子拆分为2个列子格子。
- 因此按照这个结构,我们就可以将那些不重叠排列的x布局按格子布局划分出来。最终所有子视图都将放在叶子格子里面,而子视图的放置顺序,就是按格子这棵树的深度遍历顺序来存放的。
- 叶子格子代表里面没有子格子,比如这个格子里面,格子1和格子2.1,2.2都是叶格子。但是格子2和根格子不是叶子格子,这样如果布局中有3个子视图,那么将按照格子的布局顺序逐步添加对应的视图。
- 例如 视图1 -> 填充1区域格子,视图2 -> 填充2.1区域格子,视图3 -> 填充2.2区域格子。
-
明确指定高度的
,比如第一个行子格子的高度时20。那么就会建立一个高度为20,宽度为100的行子格子 -
明确指定高度比例
,比如第二个行子格子的高度时整体高度的30%。那么久会建立一个高度为30,宽度为100的行子格子 -
明确指定生于高度比例
,比如第三个行格子的高度是剩余高度的40%,那么就会建立一个(100-20-30) * 0.4 = 20 高度并且宽度为100的行格子 -
明确指定剩余下的所有高度
,比如第四个行子格子的高度时剩余下的所有高度,那么就会建立一个高度为30,宽度为100的子格子
案例
- 建立三个高度分别为33.3333%的行子格子
* [grid addRow:1.0/3];
* [grid addRow:1.0/3];
* [grid addRow:1.0/3];
- 建立一个高度为剩余33.3333%的行格子,第二个高度为剩余高度50%的行格子,第三个为剩余全高度的行格子
* [grid addRow:-1.0/3];
* [grid addRow:-1.0/2];
* [grid addRow:MyLayoutSize.fill];
- 建立3个为剩余全高度的行格子
* [grid addRow:MyLayoutSize.fill];
* [grid addRow:MyLayoutSize.fill];
* [grid addRow:MyLayoutSize.fill];
- 建立为JSON形式
* grid.gridDictionary = @{"rows":[{"size":"33.33%"}, {"size":"33.33%"}, {"size":"33.33%"}}]}
* grid.gridDictionary = @{"rows":[{"size":"-33.33%"}, {"size":"-50%"}, {"size":"fill"}]}
* grid.gridDictionary = @{"rows":[{"size":"fill"},{"size":"fill"},{"size":"fill"}]};
这里面可见:第一种和第二种都需要指定一个除不尽的小数
;但是第三种和第四种就不需要指定任何小数
布局尺寸描述
-
@{kMyGridSize:@(20)}
表示尺寸是20
-
@{kMyGridSize:@"50%"}
表示尺寸是总体的50%
-
@{kMyGridSize:@"-50%"}
表示是剩余的50%
-
@{kMyGridSize:vMyGridSizeWrap}
表示尺寸由子格子包裹
-
@{kMyGridSize:vMyGridSizeFill}
表示尺寸均分和填充剩余的高度或者宽度
anchor锚点
用于栅格
,表示设置为YES时,栅格也放入一个对应的子视图
placeholder
用于叶子栅格
,表示设置为YES时,叶子栅格不会放入一个对应的子视图
视图重叠
MyGirdLayout_Demo.gif数据
Demo4
{"padding":"{10,0,10,0}","tag":1000,"rows":[{"size":120},{"size":20},
{"size":150,"tag":1,"cols":[{"size":"fill","rows":[{"size":"fill","cols":
[{"size":"20%"},{"size":"20%"},{"size":"20%"},{"size":"20%"},
{"size":"20%"}]},{"size":"fill","cols":[{"size":"20%"},{"size":"20%"},
{"size":"20%"},{"size":"20%"},{"size":"20%"}]}]}]},{"size":5,},
{"size":"fill","cols":[{"size":"50%","padding":"{0,5,0,5}","right-
borderline":{"head":1,"tail":1,"offset":1,"thick":
1,"color":"#EEEEEE"},"bottom-borderline":{"head":1,"tail":1,"offset":
1,"thick":1,"color":"#EEEEEE"},"tag":2,"action":"handleTap:","rows":
[{"size":40,"cols":[{"anchor":true,"size":80,"padding":"{5,5,5,5}","space":
5,"rows":[{"size":"fill"},{"size":"fill"}]},
{"size":"fill","padding":"{5,5,5,5}","space":5,"rows":[{"size":"fill"},
{"size":"fill"}]}]},{"space":5,"size":"fill","cols":[{"padding":"{5, 5, 5,
5}","size":"fill"},{"padding":"{5, 5, 5, 5}","size":"fill"}]},
{"overlap":"bottom|left","padding":"{0,0,5,0}"}]},
{"size":"50%","padding":"{0,5,0,5}","right-borderline":{"head":1,"tail":
1,"offset":1,"thick":1,"color":"#EEEEEE"},"bottom-borderline":{"head":
1,"tail":1,"offset":1,"thick":
1,"color":"#EEEEEE"},"action":"handleTap:","tag":3,"rows":
[{"size":"fill","cols":[{"size":"fill","rows":[{"size":"wrap"},
{"size":"wrap"},{"padding":"{5, 5, 5, 5}","size":"wrap"}]},{"padding":"{5,
5, 5, 5}","size":"fill"}]}]}]},{"size":"fill","cols":
[{"size":"50%","padding":"{0,5,0,5}","right-borderline":{"head":1,"tail":
1,"offset":1,"thick":1,"color":"#EEEEEE"},"bottom-borderline":{"head":
1,"tail":1,"offset":1,"thick":1,"color":"#EEEEEE"},"tag":
3,"action":"handleTap:","rows":[{"size":"fill","cols":
[{"size":"fill","rows":[{"size":"wrap"},{"size":"wrap"},{"padding":"{5, 5, 5, 5}","size":"wrap"}]},{"padding":"{5, 5, 5, 5}","size":"fill"}]}]},
{"size":"50%","padding":"{0,5,0,5}","right-borderline":{"head":1,"tail":
1,"offset":1,"thick":1,"color":"#EEEEEE"},"bottom-borderline":{"head":
1,"tail":1,"offset":1,"thick":1,"color":"#EEEEEE"},"tag":
3,"action":"handleTap:","rows":[{"size":"fill","cols":
[{"size":"fill","rows":[{"size":"wrap"},{"size":"wrap"},{"padding":"{5, 5,
5, 5}","size":"wrap"}]},{"padding":"{5, 5, 5, 5}","size":"fill"}]},
{"overlap":"bottom|left","padding":"{0,0,5,0}"}]}]}]}
Demo5
{"rows":[{"size":240,"padding":"{10,10,5,10}","space":5,"cols":
[{"size":"40%","anchor":true,"tag":222,"padding":"{0,20,0,20}","rows":
[{"size":35,"anchor":"true","rows":[{"size":"fill"}]},{"size":
30,"anchor":"true","rows":[{"size":"fill"}]}]},{"size":"30%","space":
5,"rows":[{"size":"fill","tag":333,"anchor":"true","rows":[{"size":30}]},
{"size":"fill","anchor":"true","tag":333,"rows":[{"size":30}]}]},
{"size":"30%","space":5,"rows":[{"size":"fill","tag":
333,"anchor":"true","rows":[{"size":30}]},
{"size":"fill","anchor":"true","tag":333,"rows":[{"size":30}]}]}]},
{"size":"fill","anchor":true,"tag":111,"top-borderline":{"thick":
10,"offset":5,"color":"#D1D1D1"},"space":
5,"padding":"{10,10,10,10}","rows":[{"size":40,"tag":1},
{"size":"fill","space":10,"cols":[{"size":"fill","anchor":true,"tag":
2,"rows":[{"size":"fill","placeholder":true},{"size":
50,"anchor":true,"cols":[{"placeholder":true,"size":"50%"},
{"size":"50%"}]}]},{"size":"fill","anchor":true,"tag":2,"rows":
[{"size":"fill","placeholder":true},{"size":50,"anchor":true,"cols":
[{"placeholder":true,"size":"50%"},{"size":"50%"}]}]}]},{"size":25,"bottom-
borderline":{"thick":1,"color":"#D1D1D1"}},{"size":
40,"padding":"{10,5,10,5}","cols":[{"size":"fill"},{"size":"wrap"}]}]}]}
网友评论