Flutter学习之ListView和GridView以及Padding Row Column Expanded布局组件

704 阅读3分钟

这里仅作为自己记录这些属性的使用。

ListView的两种创建方法

  1. ListView()
  2. ListView.builder()

GridView两种创建方式

  • 静态生成:GridView.count()
  • 动态生成:GridView.builder()
//静态生成GridView数据获取
List<Widget>  _getDataList(){
  var tempList = dataDataJsonDicList.map((dic){
    return Container(
      child: C
        children: [
          Image.network(dic['imageUrl']),
          //设置两个控件之间的间距
          SizedBox(height: 10,),
          Text(
            dic['title'],
            //文字对其方式
            textAlign: TextAlign.center,
            //文字样式
            style: TextStyle(
              //大小
              fontSize: 20,
              //粗细
              fontWeight: FontWeight.w900
            ),
          )
        ],
      ),
      //设置Container样式
      decoration: BoxDecoration(
      //设置边框
        border: Border.all(
          color: Color.fromRGBO(233, 233, 233, 0.9),
          width: 1
        )
        //设置圆角
        borderRadius: BorderRadius.all(
            Radius.circular(20)
        ),
      ),
    );
  });
  return tempList.toList();
}
//静态生成
GridView.count(
    padding: EdgeInsets.all(10),
    //左右高度
    crossAxisSpacing: 10,
    //上下高度
    mainAxisSpacing:10,
    
    children: this._getDataList(),
    //网格每行数量
    crossAxisCount: 2,
    // //宽高比
    childAspectRatio: 0.6,
);
//动态生成GridView数据获取
Widget  _dynamicGetDataList(content, index){
  return Container(
    child: Column(
      children: [
        Image.network(dataDataJsonDicList[index]['imageUrl']),
        SizedBox(height: 10,),
        Text(
          dataDataJsonDicList[index]['title'],
          textAlign: TextAlign.center,
          style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.w900
          ),
        )
      ],
    ),
    //设置边框
    decoration: BoxDecoration(
        border: Border.all(
            color: Color.fromRGBO(233, 233, 233, 0.9),
            width: 1
        )
    ),
  );
}
//动态生成GridView
GridView.builder(
      //使用builder生成GridView 设置item之间的上下间距/左右间距/每行item数量/item宽高比,是放在代理里面
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisSpacing: 10,
      mainAxisSpacing: 10,
      crossAxisCount: 2,
      childAspectRatio: 0.6
    ),
    itemCount: dataDataJsonDicList.length,
    itemBuilder: this._dynamicGetDataList,
);

Paddiing

例如:Image组件没有Padding属性。又想设置上下左右间距。可以这样下去

Padding(
  child: Image.network('imageUrl'),
  padding: EdgeInsets.all(10),
)

使用一个Padding包裹他。然后在Padding内部的padding属性设置上下左右间距。

Row

Row水平布局组件

这里先贴出IconContainer的代码 ,下面会用到。

class IconContainer extends StatelessWidget {

  double size = 32;
  Color color = Colors.yellow;
  IconData icon = Icons.home;

  IconContainer(this.icon, {this.color = Colors.yellow, this.size = 32});

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      height: 100,
      width: 100,
      child: Center(
        child: Icon(this.icon, color: Colors.blue,size: this.size),
      ),
      color: this.color,

    );
  }
}
Row(
  //X轴样式调整
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  //Y轴样式调整
  crossAxisAlignment: CrossAxisAlignment.end,
  children: [
    IconContainer(Icons.home,color: Colors.yellow,),
    IconContainer(Icons.map,color: Colors.brown),
    IconContainer(Icons.list,color: Colors.orange,),
  ],
),

Column

Column垂直布局组件 使用方式同Row

Expanded

布局控件。

例如 实现图中效果

IMG_715DBF8DBAC2-1.jpeg

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Expanded(child: IconContainer(Icons.home,color: Colors.yellow,),flex: 1,),
    Expanded(child: IconContainer(Icons.map,color: Colors.brown),flex: 2,),
    Expanded(child: IconContainer(Icons.list,color: Colors.orange,),flex: 1,)
  ],
);

不要在乎 IconContainer 这是自定义的一个组件。主要是 flex 属性的设置。 这里的代码我理解为 fit一共设置值为4,会把屏幕宽度分为4块。然后根据设置的值自动分割。

如果想要实现一个固定宽度,然后另外一个自适应,就像下图。

IMG_C8016A75BAAB-1.jpeg

可以这样写。

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Expanded(child: IconContainer(Icons.home,color: Colors.yellow,),flex: 1,),
    IconContainer(Icons.map,color: Colors.brown),
  ],
);

这里没有被Expanded包裹的IconContainer是固定宽度,然后另外一个就会自适应宽度。 也就是说Expanded会打破他包裹的组件内部设置的宽高。

最后,使用这些组件实现下图效果。

IMG_3F1EF6D564D1-1.jpeg

第一时间想到的是,需要Column嵌套Row,然后Row再嵌套 Column。 好的,下面开始“套娃”。

Container(
  padding: EdgeInsets.all(10),
  child: Column(
    children: [
      Container(
        height: 200,
        color: Colors.black,
      ),
      //设置两个控件之间的间距
      SizedBox(height: 10),
      Container(
        child: Row(
          children: [
            Expanded(
              flex: 2,
              child: Container(
                height: 200,
                child: Container(color: Colors.yellow,),
              )
            ),
            SizedBox(width: 10),
            Expanded(
              flex: 1,
              child: Container(
                child: Column(
                  children: [
                    Container(
                      child: Container(color: Colors.yellow,),

                      height: 95,
                    ),
                    SizedBox(height: 10),
                    Container(
                      child: Container(color: Colors.yellow,),
                      height: 95,
                    ),
                  ],
                ),
              )
            ),
          ],
        ),
      )
    ],
  ),
);

写完自己的代码,然后对比学习资料,发现想法差不多。就是这个嵌套,简直是噩梦。 下图未代码编译结果。

image.png