美文网首页
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