美文网首页
Flutter 学习笔记5-构建布局

Flutter 学习笔记5-构建布局

作者: 三流之路 | 来源:发表于2018-12-31 16:54 被阅读0次

构建一个布局

  1. 创建一个 widget 容纳可见对象

    比如文字 Text('Hello World', style: TextStyle(fontSize: 32.0))

    比如图片 Image.asset('images/myPic.jpg', fit: BoxFit.cover)

    比如 icon Icon(Icons.star, color: Colors.red[500])

  2. 将上面的 widget 作为一个 child 和 children 添加到布局 widget,这个 widget 提供边距,对齐等功能。

    Center(
      child: Text('Hello World', style: TextStyle(fontSize: 32.0))
    )
    
  3. 将布局 widget 添加到页面

    如果是 Material 的,可用 Scaffold,它提供了一个默认 banner,背景色,并且具有添加 drawer,snack bar 和底部 sheet 的API。

    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Text('Hello World', style: TextStyle(fontSize: 32.0)),
          ),
        );
      }
    }
    

    如果不用 Material,没有 AppBar,背景色,标题这样,就用一个普通的 Container。

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(color: Colors.white),
          child: Center(
            child: Text('Hello World',
                textDirection: TextDirection.ltr,
                style: TextStyle(fontSize: 40.0, color: Colors.black87)),
          ),
        );
      }
    }
    

垂直和水平放置多个 widget

使用 Row 水平排列,用 Column 垂直排列。它们都通过 children 添加一个子 widget 列表。

15462344685653.png

分析上图布局:

  1. 最外层是一个 Row,有两个 child:第一列是一个 Column,第二列是一个 Image
  2. 左侧的 Column 有四个 child:第一行和第二行是 Text,第三行和第四行是一个 Row
15462347010396.png

这样一层一层地分析,复杂 widget 就变成了最基础的 widget。

对齐 widgets

15462348828519.png 15462348950053.png

对于 Row,主轴是水平方向,对于 Column,主轴是垂直方向。使用 mainAxisAlignmentcrossAxisAlignment 属性来对齐它们的子项。

将之前的示例代码中的图像改成

Widget rowImageSection = Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/lake.jpg', width: 100, height: 80,),
    Image.asset('images/lake.jpg', width: 100, height: 80,),
    Image.asset('images/lake.jpg', width: 100, height: 80,),
  ],
);
   
Widget columnImageSection = Container(
  height: 300,
  color: Colors.blueGrey,
  child: Column(

    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      Image.asset('images/lake.jpg', width: 100, height: 80,),
      Image.asset('images/lake.jpg', width: 100, height: 80,),
      Image.asset('images/lake.jpg', width: 100, height: 80,),
    ],
  )
); 

return MaterialApp(
  ...
  home: Scaffold(
    ...
    body: ListView(
      children: [
//      Image.asset(
//        'images/lake.jpg',
//        width: 600.0,
//        height: 240.0,
//        fit: BoxFit.cover,
//      ),
      rowImageSection,
      columnImageSection,
      titleSection,
      buttonSection,
      textSection,
    ],
  ),
),
);

分别有一行和一列,图片宽 100 px,高 80 px,列的高度是 300 px,大于三张图片高度的和,其中列设置了背景颜色,以便区分。

  1. spaceEvenly 前后均匀分配空闲空间

    屏幕快照 2018-12-31 下午2.39.07.png
  2. spaceAround 左右两侧的距离是中间的一半

    屏幕快照 2018-12-31 下午2.51.01.png
  3. spaceBetween 两侧没有距离,只在 child 之间平均分配

    屏幕快照 2018-12-31 下午2.52.27.png
  4. center 居中显示

    屏幕快照 2018-12-31 下午2.43.08.png
  5. start 从开始处排列

    屏幕快照 2018-12-31 下午2.44.28.png
  6. end 排字最后

    屏幕快照 2018-12-31 下午2.47.41.png

调整 widget

children: [
  Image.asset('images/lake.jpg', width: 200,),
  Image.asset('images/lake.jpg', width: 200,),
  Image.asset('images/lake.jpg', width: 200,),
]

如果布局太大超出设备尺寸,边缘显示会有问题,如下图

屏幕快照 2018-12-31 下午3.20.36.png

可将 RowColumn 中的 child 放入 Expanded,会使得子 widget 自适应。

children: [
  new Expanded(
    child: Image.asset('images/lake.jpg', width: 200,),
  ),
  new Expanded(
    child: Image.asset('images/lake.jpg', width: 200,),
  ),
  new Expanded(
    child: Image.asset('images/lake.jpg', width: 200,),
  ),
],
屏幕快照 2018-12-31 下午3.27.31.png

Expanded widget 有 flex 属性,是一个整数,用于确定 widget 的弹性系数,默认值是 1。

Widget rowImageSection = Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    new Expanded(
      child: Image.asset('images/lake.jpg', width: 200,),
    ),
    new Expanded(
      flex: 2,
      child: Image.asset('images/lake.jpg', width: 200,),
    ),
    new Expanded(
      child: Image.asset('images/lake.jpg', width: 200,),
    ),
  ],
);

crossAxisAlignment 指定 Row 的垂直方向居中,中间是左右两边的两倍。

屏幕快照 2018-12-31 下午3.29.03.png

聚集 widgets

默认情况下,行和列沿着主轴会尽可能占用尽可能多的空间,但如果要将它们聚集在一起,可以将 mainAxisSize 设为 MainAxisSize.min。

var packedRow = Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.black),
    Icon(Icons.star, color: Colors.black),
  ],
);
15462421984413.png

只是即使没有 mainAxisSize: MainAxisSize.min 这一句效果也一样。

相关文章

网友评论

      本文标题:Flutter 学习笔记5-构建布局

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