美文网首页
栅格布局

栅格布局

作者: 覆雪古树 | 来源:发表于2017-10-21 13:57 被阅读0次

    初衷和项目源代码

    主要是解决:同一份数据,可以动态切换不同的布局。如果模型数据很多条,那么就肯定用UITtableview

    原理

    • MyGirdeLayout->栅格布局:树形结构

    • UIView.subviews->子视图:平面结构

    • 栅格布局:

    1. 将一个矩形的视图区域按行或者按列的方式划分为多个子区域,子区域根据布局的要求可以继续递归划分。栅格布局里面的子视图将按照添加的顺序依次填充到对应的叶子区域中去的布局方式
    2. 通过一套自定义的布局体系来划分位置和尺寸,添加到栅格布局里面的子视图将不再需要指定位置和尺寸而是由栅格布局中的子栅格来完成,因此可以很很方便的调整布局结构,从而实现动态布局的能力。 所谓栅格其实就是一个矩形区域,我们知道一个视图其实就是一个矩形区域,而子视图的frame属性其实就是父视图中的某个特定的子区域部分
    3. 既然子视图最终占据的是父视图的某个子矩形区域。那么我们也可以先将一个矩形区域按照某种规则分解为多个子矩形区域,然后再将子视图填充到对应的子矩形区域中去,这就是栅格布局的实现思想

    叶子格子和非叶子格子区别

    • 叶子格子表示里面没有子格子而非叶子格子表示里面有子格子

    • 非叶子栅格只能设置一个方向的停靠,具体只能设置左中右或者上中下

    • 叶子栅格如果设置了gravity则填充的子视图必须要设置明确的尺寸

    视图组

    1. 原理
    MyGridLayout_ViewGroup.png
    1. 数据

      {"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"}]}]}
      
    2. 视图

      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];
      
    3. 这样就可以根据数据的Tag来指定标签内才会放置绑定的视图组

    布局技巧

    拆分子格子几种方法

    描述

    MyGridLayout_Demo1.png
    • 把格子拆分为2个行子格子,然后第2个行子格子拆分为2个列子格子。
    • 因此按照这个结构,我们就可以将那些不重叠排列的x布局按格子布局划分出来。最终所有子视图都将放在叶子格子里面,而子视图的放置顺序,就是按格子这棵树的深度遍历顺序来存放的。
    • 叶子格子代表里面没有子格子,比如这个格子里面,格子1和格子2.1,2.2都是叶格子。但是格子2和根格子不是叶子格子,这样如果布局中有3个子视图,那么将按照格子的布局顺序逐步添加对应的视图。
    • 例如 视图1 -> 填充1区域格子,视图2 -> 填充2.1区域格子,视图3 -> 填充2.2区域格子。
    1. 明确指定高度的,比如第一个行子格子的高度时20。那么就会建立一个高度为20,宽度为100的行子格子
    2. 明确指定高度比例,比如第二个行子格子的高度时整体高度的30%。那么久会建立一个高度为30,宽度为100的行子格子
    3. 明确指定生于高度比例,比如第三个行格子的高度是剩余高度的40%,那么就会建立一个(100-20-30) * 0.4 = 20 高度并且宽度为100的行格子
    4. 明确指定剩余下的所有高度,比如第四个行子格子的高度时剩余下的所有高度,那么就会建立一个高度为30,宽度为100的子格子

    案例

    1. 建立三个高度分别为33.3333%的行子格子
        * [grid addRow:1.0/3];  
        * [grid addRow:1.0/3];  
        * [grid addRow:1.0/3];
    
    1. 建立一个高度为剩余33.3333%的行格子,第二个高度为剩余高度50%的行格子,第三个为剩余全高度的行格子
        * [grid addRow:-1.0/3];  
        * [grid addRow:-1.0/2];  
        * [grid addRow:MyLayoutSize.fill];
    
    1. 建立3个为剩余全高度的行格子
        * [grid addRow:MyLayoutSize.fill]; 
        * [grid addRow:MyLayoutSize.fill]; 
        * [grid addRow:MyLayoutSize.fill];
    
    1. 建立为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"}]};
    

    这里面可见:第一种和第二种都需要指定一个除不尽的小数;但是第三种和第四种就不需要指定任何小数

    布局尺寸描述

    1. @{kMyGridSize:@(20)} 表示尺寸是20

    2. @{kMyGridSize:@"50%"} 表示尺寸是总体的50%

    3. @{kMyGridSize:@"-50%"} 表示是剩余的50%

    4. @{kMyGridSize:vMyGridSizeWrap} 表示尺寸由子格子包裹

    5. @{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"}]}]}]}
    

    相关文章

      网友评论

          本文标题:栅格布局

          本文链接:https://www.haomeiwen.com/subject/wmtiuxtx.html