美文网首页Flutter圈子FlutterJavaScript 进阶营
Flutter 布局常用的 widgets(Common lay

Flutter 布局常用的 widgets(Common lay

作者: AnRFDev | 来源:发表于2018-06-26 15:53 被阅读222次

    简单列举总结一下常用的布局widget。
    Flutter有丰富的layout组件库。其中有一些是常用库。
    下面的widget分为两类:标准组件和来自Material Components的特殊组件。
    只有Material App能够使用Material Components的组件。

    标准组件 - Standard widgets

    • Container
      • 给一个组件添加 padding, margins, 边界(borders), 背景颜色或其它装饰(decorations)。
    • GridView
      • 将多个widget放在一个可滑动的表格中。
    • ListView
      • 将多个widget放在一个可滑动的列表中。
    • Stack
      • 在一个widget上面盖上另一个widget。

    Material Components

    • Card
      • 将一些相近的信息装进一个有圆角和阴影的盒子里。
    • ListTile
      • 一个Row中装载最多3行文字;可选则在前面或尾部添加图标。

    Container

    Container用法比较自由。可以把整个layout放进container里面,然后改变背景颜色或图片。

    Container 小结:

    • 添加 padding, margins, 和边界(borders)
    • 能够更好背景颜色和图片
    • 包含一个单独的子widget,这个子widget可以是Row、Column或一个widget树的根widget
    container结构

    测试代码widgetdemo/container_page.dart

    import 'package:flutter/material.dart';
    import 'package:demo_flutter/widgetdemo/container_page.dart';
    // 引入自定义的包......
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Container demo 1',
          theme: new ThemeData(primarySwatch: Colors.brown),
          home: new ContainerDemoPage(), // 这里换上想要测试的界面
        );
      }
    }
    

    widgetdemo/container_page.dart代码

    import 'package:flutter/material.dart';
    
    /// container示例界面
    class ContainerDemoPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _ContainerDemoPageState();
    }
    
    class _ContainerDemoPageState extends State<ContainerDemoPage> {
      @override
      Widget build(BuildContext context) {
        Expanded imageExpanded(String img) {
          return new Expanded(child: new Container(
            decoration: new BoxDecoration(
                border: new Border.all(width: 10.0, color: Colors.black38),
                borderRadius: const BorderRadius.all(
                    const Radius.circular(8.0))),
            margin: const EdgeInsets.all(4.0),
            child: new Image.asset(img),
          ));
        }
    
        var container = new Container(
          decoration: new BoxDecoration(color: Colors.black26),
          child: new Column(
            children: <Widget>[
              new Row(children: <Widget>[
                imageExpanded('images/c1.jpg'),
                imageExpanded('images/c2.jpg'),
              ],),
              new Row(children: <Widget>[
                imageExpanded('images/d1.jpg'),
                imageExpanded('images/d2.jpg'),
              ],),
              new Row(children: <Widget>[
                imageExpanded('images/p1.jpg'),
              ],)
            ],
          ),
        );
    
        return new Scaffold(
          appBar: new AppBar(title: new Text('Container Page demo'),),
          body: new Center(
            child: container,
          ),
        );
      }
    }
    
    container示例

    GridView

    用GridView来将widget放入一个2维的列表中。
    GridView提供了2个预装配好的列表,也可以自己建立自定义列表。
    GridView支持滚动。

    GridView 小结:

    • 将多个widget放进一个表格中
    • 当超出渲染范围时,自动提供滚动功能
    • 可自定义格子,也可用下面提供的2种
      • GridView.count 指定列的数目
      • GridView.extent 允许指定子项的最大像素宽度

    示例1 - 用GridView.extent

    GridView.extent指定子项占据的最大宽度

    import 'package:flutter/material.dart';
    
    /// gridView示例界面1
    class GridDemo1Page extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _GridDemo1PageState();
    }
    
    class _GridDemo1PageState extends State<GridDemo1Page> {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(title: new Text('Grid Page 1 demo'),),
          body: new Center(
            child: buildGrid(),
          ),
        );
      }
    
      List<Container> _buildGridTileList(int count) {
        return new List<Container>.generate(count, (int index) =>
        new Container(child: new Image.asset('images/pic${index + 1}.jpg'),));
      }
    
      Widget buildGrid() {
        return new GridView.extent(
          maxCrossAxisExtent: 150.0,
          padding: const EdgeInsets.all(4.0),
          mainAxisSpacing: 4.0,
          crossAxisSpacing: 4.0,
          children: _buildGridTileList(30),);
      }
    }
    
    用GridView.extent

    示例2 - 用GridView.count

    crossAxisCount设为2,分成2列。

      Widget buildGrid() {
        var countGrid = GridView.count(
          crossAxisCount: 2,
          mainAxisSpacing: 4.0,
          crossAxisSpacing: 4.0,
          padding: const EdgeInsets.all(4.0),
          childAspectRatio: 1.3,
          children: _buildGridTileList(30),
        );
        return countGrid;
      }
    
    GridView.count示例

    ListView

    ListView能以列的形式展示数据。当内容超过渲染范围时,自动提供滚动的功能。

    ListView 小结

    • 把子视图装进列表中
    • 水平或竖直都可以
    • 支持滑动
    • 相比于Column,可选配置比较少,但更易用并且支持滑动

    和Android中的ListView差别不大

    示例1

    ListTile当做子项来装载数据。

    import 'package:flutter/material.dart';
    
    class ListViewPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _ListViewPageState();
    }
    
    class _ListViewPageState extends State<ListViewPage> {
    
      @override
      Widget build(BuildContext context) {
        List<Widget> list = <Widget>[];
        for (int i = 0; i < 30; i++) {
          list.add(new ListTile(
            title: new Text('title$i', style: _itemTextStyle,),
            subtitle: new Text('A'),
            leading: i % 3 == 0
                ? new Icon(Icons.theaters, color: Colors.blue,)
                : new Icon(Icons.restaurant, color: Colors.blue,),
          ));
        }
        return new Scaffold(
          appBar: new AppBar(title: new Text('ListView Demo'),),
          body: new Center(child: new ListView(children: list,),),
        );
      }
    }
    
    TextStyle _itemTextStyle = new TextStyle(
        fontWeight: FontWeight.w500, fontSize: 14.0);
    
    ListView参考效果图1

    另外可以参考 https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/colors_demo.dart

    Stack

    使用Stack在widget之上显示另一些widget,通常用来显示图片。
    显示的widget可以完全地把底部widget盖住。

    Stack 小结:

    • 用来在当前widget上面再盖上一层widget
    • Stack children中的第一个widget放在最下,后面的widget会一层层盖上去
    • Stack的内容不支持滚动
    • 可以裁剪超出范围的子widget

    Stack示例1

    显示一个CircleAvatar

    import 'package:flutter/material.dart';
    
    class StackPage1 extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _StackPage1State();
    }
    
    class _StackPage1State extends State<StackPage1> {
    
      @override
      Widget build(BuildContext context) {
        var stack = new Stack(
          alignment: const Alignment(0.6, 0.6),
          children: <Widget>[
            new CircleAvatar(
              backgroundImage: new AssetImage('images/android_1.jpg'),
              radius: 100.0,),
            new Container(decoration: new BoxDecoration(color: Colors.black45),
              child: new Text(
                'Android Avatar', style: new TextStyle(color: Colors.white70),),),
            new Container(decoration: new BoxDecoration(color: Colors.transparent),
              padding: const EdgeInsets.fromLTRB(0.0, 0.0, 100.0, 0.0),
              child: new CircleAvatar(
                backgroundImage: new AssetImage('images/p_box1.png'),
                backgroundColor: Colors.transparent,
                radius: 10.0,),),
          ],
        );
        return new Scaffold(
          appBar: new AppBar(title: new Text('Stack Demo 1'),),
          body: new Center(child: stack,),
        );
      }
    }
    
    Stack示例1

    Card

    Card来自Material组件库,可包含一些数据,通常用ListTile来组装。Card只有一个子widget,可以是column、row、list、grid或其它组合widget。
    默认情况下,Card把自己的尺寸缩小为0像素。可以用SizedBox来指定card的尺寸。

    Flutter中的Card有圆角和阴影效果。修改elevation可改变阴影效果。

    elevation取值范围,参考 Elevation and Shadows

    若设置的范围外的值,阴影效果会消失。

    Card 小结:

    • 实现了Material Design card
    • 用于展示相关的数据
    • 有一个子项(child),可以是column、row、list、grid或其它组合widget
    • 有圆角和阴影效果
    • 不支持滚动

    Card示例1

    将前面的ListView示例修改一下

    import 'package:flutter/material.dart';
    
    class ListViewPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _ListViewPageState();
    }
    
    class _ListViewPageState extends State<ListViewPage> {
    
      @override
      Widget build(BuildContext context) {
        List<Widget> list = <Widget>[];
        for (int i = 0; i < 30; i++) {
          list.add(new Card(child: new Column(
            children: <Widget>[
              new Image.asset(
                'images/pic${i + 1}.jpg',),
              new ListTile(
                title: new Text('title$i', style: _itemTextStyle,),
                subtitle: new Text('A'),
                leading: i % 3 == 0
                    ? new Icon(Icons.theaters, color: Colors.blue,)
                    : new Icon(Icons.restaurant, color: Colors.blue,),
              ),
            ],
          ),));
        }
        return new Scaffold(
          appBar: new AppBar(title: new Text('ListView Demo'),),
          body: new Center(child: new ListView(children: list,),),
        );
      }
    }
    
    TextStyle _itemTextStyle = new TextStyle(
        fontWeight: FontWeight.w500, fontSize: 14.0);
    
    Card示例1

    ListTile

    来自Material组件库的横向组件。可自定义3行文字及其可选的头尾图标。
    此控件常与Card或ListView一起用。

    ListTile 小结:

    • 可定制3行带图标的文字
    • 相比于Row,配置更少,但更易用

    加一个主界面

    放置一些按钮,点击跳转到相应的界面。
    使用Navigator.of(context).pushNamed(routeName)来跳转。

    import 'package:flutter/material.dart';
    import 'package:demo_flutter/widgetdemo/container_page.dart';
    import 'package:demo_flutter/widgetdemo/grid_page.dart';
    import 'package:demo_flutter/widgetdemo/listview_demo.dart';
    import 'package:demo_flutter/widgetdemo/stack_page1.dart';
    import 'package:demo_flutter/widgetdemo/button_page.dart';
    
    const String CONTAINER_DEMO_PAGE = '/a';
    
    void main() {
      runApp(new MaterialApp(
        home: new HomePage(),
        routes: {
          CONTAINER_DEMO_PAGE: (BuildContext context) => new ContainerDemoPage(),
          '/b': (BuildContext context) => new GridDemo1Page(),
          '/c': (BuildContext context) => new ListViewPage(),
          '/d': (BuildContext context) => new StackPage1(),
          '/e': (BuildContext context) => new ButtonPage(),
        },
      ));
    }
    
    class HomePage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => new _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
    
      @override
      Widget build(BuildContext context) {
        getGestureDetector(String routeName, String content) {
          return new GestureDetector (
            onTap: () {
              Navigator.of(context).pushNamed(routeName);
            },
            child: new Container (
                padding: EdgeInsets.all(20.0),
                child: new Center(child: new Text (content),)),
          );
        }
        return new Scaffold(
          appBar: new AppBar(title: new Text('Home'),),
          body: new Column(children: <Widget>[
            getGestureDetector(CONTAINER_DEMO_PAGE, 'Container Demo'),
            getGestureDetector('/b', 'Grid Demo 1'),
            getGestureDetector('/c', 'ListView Demo'),
            getGestureDetector('/d', 'Stack Demo'),
            getGestureDetector('/e', 'Button Page'),
          ],),
        );
      }
    
    }
    

    相关文章

      网友评论

      本文标题:Flutter 布局常用的 widgets(Common lay

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