Flutter 开发之组件二

Flutter 一切谐为组件!



本篇主要介绍以下几个组件:

  • Card - 卡片组件
  • CheckBox - 组件
  • Chip - 标签组件
  • Dialog - 对话框组件
  • Grid - 网格组件
  • Icon - 图标组件
  • Image - 图片组件
  • Input - TextField 组件
  • Layout - 布局组件
  • List - 列表组件

一、Card - 卡片组件

卡片可以做联系人,地址信息等,带有介绍性质的组件。


Card

class DemoPageState extends State<DemoPage> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        //背景色
        color: Colors.green,
        //卡片的z坐标 阴影的大小
        elevation: 10.0,
        //外边距
        margin: EdgeInsets.all(20.0),
        //卡片边框样式
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(20.0),
        ),
        //卡片的具体内容
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[

            const ListTile(
              leading: Icon(Icons.shopping_cart),
              title: Text(
                '苹果电脑MacBookPro',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 32.0,
                ),
              ),
              subtitle: Text(
                '配置为16核 8G内存',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 16.0,
                ),
              ),
              contentPadding: EdgeInsets.all(20.0),
            ),

            //添加两个按钮
            ButtonTheme.bar(
              child: ButtonBar(
                children: <Widget>[
                  FlatButton(
                    child: Text('购买',style: TextStyle(color: Colors.black,fontSize: 18.0),),
                    onPressed: (){},
                  ),
                  FlatButton(
                    child: Text('取消',style: TextStyle(color: Colors.black,fontSize: 18.0),),
                    onPressed: (){},
                  ),

                ],
              ),
            ),

          ],
        ),

      ),
    );
  }
}

二、CheckBox - 组件

复选框,允许用户从一组中选择多个选项。


CheckBox

2.1 CheckboxListTile

          child: CheckboxListTile(
            value: _value,
            //默认文字是否高亮
            selected: true,
            onChanged: _valueChanged,
            dense: false,
            //文字是否对齐 图标高度
            isThreeLine: false,
            //文字是否三行显示
            title: Text('整个内容'),
            // 将控件放在何处相对于文本,leading 按钮显示在文字前面,platform,trailing 按钮显示在文字后面
            controlAffinity: ListTileControlAffinity.platform,
            subtitle: Text('勾选下列选项'),
            secondary: Icon(Icons.archive),//左侧小图标
            activeColor: Colors.red,
          ),

2.2 CheckBox

复选框

        Checkbox(
          //激活时的颜色
          activeColor: Colors.red,
          //是否被选中
          value: 0 == currentIndex,
          //如果tristate的值为true 那个value的值可能为true false null
          tristate: false,
          //值发生变化
          onChanged: (bool check){
            setState(() {
              if(check){
                currentIndex = 0;
              }
            });
          },
        ),

三、Chip - 标签组件

标签,一个 Material widget,它可以将一个复杂内容实体展现在一个小块中,如联系人。


Chip

  • Chip
  • ActionChip
  • FilterChip
  • ChoiceChip
             Chip(
                label: Text('Flutter'),
                //背景色
                backgroundColor: Colors.orange,
              ),
              Chip(
                label: Text('Flutter'),
                //头部
                avatar: CircleAvatar(
                  backgroundColor: Colors.green,
                  child: Text('Flutter'),
                ),
              ),

四、Dialog - 对话框组件

Dialog 的主要作用:提示类、做交互

  • AlertDialog //一个会中断用户操作的对话款,需要用户确认


AlertDialog

  • SimpleDialog //简单对话框可以显示附加的提示或操作


SimpleDialog

  //打开AboutDialog,介绍之类的
  void showAboutDialog(BuildContext context) {
    //调用方法
    showDialog(
        context: context,
        //构造器
        builder: (_) => new AboutDialog(
              applicationName: 'AndroidStudio',
              applicationIcon: Icon(Icons.apps),
              applicationVersion: 'V3.1.2',
              children: <Widget>[Text('这是AndroidStudio')],
            ));
    }


  //打开showSimpleDialog
  void showSimpleDialog(BuildContext context) {
    //调用方法
    showDialog<Null>(
        context: context,
        //构造器
        builder: (BuildContext context) => new SimpleDialog(
          title: Text('选择'),
          children: <Widget>[
            //SimpleDialog选项
            SimpleDialogOption(
              child: Text('选项1'),
              onPressed: (){
                Navigator.of(context).pop();
              },
            ),
            SimpleDialogOption(
              child: Text('选项2'),
              onPressed: (){
                Navigator.of(context).pop();
              },
            ),
          ],
        ));
   }


  //AlertDialog
  void showAlertDialog(BuildContext context) {
    //调用方法
    showDialog<void>(
        context: context,
        //构造器
        builder: (BuildContext context) => new AlertDialog(
          title: Text('标题'),
          //内容
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
                Text('较长的list...'),
              ],
            ),
          ),
          //操作按钮
          actions: <Widget>[
            FlatButton(
              child: Text('确定'),
              onPressed: (){
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: Text('取消'),
              onPressed: (){
                Navigator.of(context).pop();
              },
            ),
          ],
        ));
  }

五、Grid - 网格组件

5.1 GridTitle

网格标题,网格里展示图片、文字、标题之类的组件。GridView

  • GridTile
  • GridTileBar
  • GridPaper
 //风格标题基本用法
              GridTile(
                header: Text('grid title'),
                child: Image.asset('assets/cat.jpeg'),
                footer: Text('grid footer'),
              ),
              Image.asset('assets/cat.jpeg'),
              GridTile(
                //GridTile按钮
                header: GridTileBar(
                  //标题
                  title: Text('header',style: TextStyle(color: Colors.red),),
                  //subtitle: Text('header',style: TextStyle(color: Colors.red),),
                  //前置图标
                  leading: Icon(Icons.print,color: Colors.green,),
                ),
                child: Image.asset('assets/cat.jpeg',fit: BoxFit.cover,),
                footer: GridTileBar(
                  //标题
                  title: Text('header',style: TextStyle(color: Colors.red),),
                  //subtitle: Text('header',style: TextStyle(color: Colors.red),),
                  //前置图标
                  leading: Icon(Icons.favorite,color: Colors.green,),
                ),

5.2 GridView

网格组件,是一个重要组件

几种创建方式:

_buildGridExtent //可以扩展的
_buildGridCount //指定列数
_buildGridSliver
_buildGridCustom

Widget _buildGridExtent() {
    return GridView.extent(
      //横轴的最大长度
      maxCrossAxisExtent: 180.0,
      //内边距
      padding: EdgeInsets.all(4.0),
      //垂直方向的间距
      mainAxisSpacing: 4.0,
      //水平方向的间距
      crossAxisSpacing: 4.0,
      children: _buildGridTitleList(30),
    );
  }

  //创建指定列数的Grid
  Widget _buildGridCount() {
    return GridView.count(
      //指定多少列
      crossAxisCount: 4,
      //内边距
      padding: EdgeInsets.all(4.0),
      //垂直方向的间距
      mainAxisSpacing: 4.0,
      //水平方向的间距
      crossAxisSpacing: 4.0,
      children: _buildGridTitleList(30),
    );
  }

  //可懒加载的Grid 只有可见的部分加载
  Widget _buildGridSliver() {
    return CustomScrollView(
      primary: false,
      slivers: <Widget>[
        SliverPadding(
          padding: EdgeInsets.all(20.0),
          sliver: SliverGrid.count(
            crossAxisCount: 2,
            crossAxisSpacing: 10.0,
            children: _buildGridTitleList(30),
          ),
        ),
      ],
    );
  }

  //SliverGridDelegateWithFixedCrossAxisCount可以指定列的个数的Grid
  //SliverGridDelegateWithMaxCrossAxisExtent根据每个宽度自动计算的Grid
  Widget _buildGridCustom() {
    return GridView.custom(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 5,
        mainAxisSpacing: 4.0,
        crossAxisSpacing: 4.0,
      ),
      childrenDelegate: SliverChildBuilderDelegate(
        (context, index) {
          return Image.asset('assets/cat.jpeg');
        },
        childCount: 30,
      ),
    );
  }

  List<Container> _buildGridTitleList(int count) {
    return List.generate(
        count,
        (int index) => Container(
              child: Image.asset('assets/cat.jpeg'),
            ));
  }

六、Icon - 图标组件


Icon

6.1 Icon - 图标组件

iconfont

 //自带图标
          Icon(
            //图标
            Icons.favorite,
            //颜色
            color: Colors.redAccent,
            //大小
            size: 48.0,
          ),

          //图片Icon
          ImageIcon(
            AssetImage('assets/phone.png'),
            color: Colors.green,
            size: 48.0,
          ),

          //可交互的Icon
          IconButton(
            icon: Icon(Icons.print),
            onPressed: (){},
          ),

6.2 IconData - 字体图标

 child: Column(children: <Widget>[
        Icon(
          IconData(
              //code
              0xe8ad,
              //字体
              fontFamily: 'MaterialIcons'),
          color: Colors.redAccent,
        ),
        Icon(
          IconData(
            //code
              61447,
              //字体
              fontFamily: 'FontAwesome'),
          color: Colors.green,
          size: 68.0,
        ),

        Icon(
          IconData(
            //code
              61454,
              //字体
              fontFamily: 'FontAwesome'),
          color: Colors.green,
          size: 68.0,
        ),

      ]),

6.3 IconTheme - 图标主题

return Center(
      //图标主题
      child: IconTheme(
        //图标主题数据
        data: IconThemeData(
            color: Colors.green,
            //透明度
            opacity: 0.5,
        ),
        child: Row(
          children: <Widget>[
            Icon(
              Icons.favorite_border,
              size: 48.0,
            ),
            Padding(
              padding: EdgeInsets.all(20.0),
              child: Text(
                '喜欢',
                style: TextStyle(fontSize: 44.0),
              ),
            ),
          ],
        ),
      ),
    );

七、Image - 图片组件

一个显示图片的 widget。


Image

assets and images

7.1 AssetImage

资源图片

在资源配置文件中添加资源 pubspec.yaml

  assets:
    - assets/cat.jpeg
    - assets/view.jpeg
    - assets/flower.jpeg
    - assets/flutter.png
            child: CircleAvatar(
              backgroundImage: AssetImage('assets/cat.jpeg'),
            ),

            child: Image(
              width: 300.0,
              height: 300.0,
              image: AssetImage('assets/view.jpeg'),
            ),

           Image(
              //可缩放的图片组件 scale值越大 图片越小
              image: ExactAssetImage('assets/flutter.png',scale: 1.5,),
            ),

7.2 BoxDecoration - 装饰图片

      //装饰器
      decoration: BoxDecoration(
        color: Colors.greenAccent,
        //装饰图片
        image: DecorationImage(
          //使用资源图片
          image: AssetImage(
            'assets/flower.jpeg',
          ),
          fit: BoxFit.contain,
          //对齐方式
          alignment: Alignment.center,
        ),
      ),

7.3 FileImage - 文件图片

class DemoPageState extends State<DemoPage> {
  //图片文件
  File _image;

   //异步获取本地文件
  Future getImage() async {
    var image = await ImagePicker.pickImage(source: ImageSource.gallery);

    setState(() {
      _image = image;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[
          Center(
              child: _image == null
                  ? Text('你还未选择任何图片')
                  //文件图片设置
                  : Image.file(
                      _image,
                      //缩放
                      scale: 0.5,
                      //填充模式
                      fit: BoxFit.cover,
                    )),
          //选择图片动作
          RaisedButton(
            onPressed: getImage,
            child: Text(
              '点击选择图片',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ],
      ),
    );
  }
}

7.4 Image-图片组件

        children: <Widget>[
          //资源图片 可添加缩放值
          Image.asset('assets/flower.jpeg',scale: 2.5,),
          //网络图片 可添加缩放值
          Image.network(
            'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2756575517,833879878&fm=200&gp=0.jpg',
            scale: 2.5,
          ),
          //本地图片
          //Image.file(file),
          //控制图片大小
          SizedBox(
            width: 200.0,
            height: 200.0,
            child: Image.asset('assets/flower.jpeg',fit: BoxFit.cover,),
          ),
        ],

八、Input - TextField 组件

TextField 是最常用的文本输入 widget。默认情况下,TextField 有一个下划线装饰(decoration)。可以通过提供给 decoration 属性设置一个 InputDecoration 来添加一个标签、一个图标、提示文字和错误文本。 要完全删除装饰(包括下划线和为标签保留的空间),将 decoration 明确设置为空即可。

TextFormField 包裹一个 TextField 并将其集成在 Form 中。你要提供一个验证函数来检查用户的输入是否满足一定的约束(例如,一个电话号码)或当你想将 TextField 与其他 FormField 集成时,使用 TextFormField。

有两种获取用户输入的主要方法:

  • 处理 onChanged回调
  • 提供一个TextEditingController.

  • TextField


TextField

class LoginPageState extends State<LoginPage>{

  //文本编辑控制器
  TextEditingController usernameController = TextEditingController();

  TextEditingController passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[

        TextField(
          controller: usernameController,
          //TextCapitalization.words 将每个单词的首字母大写
          //TextCapitalization.sentences 将首字母大写
          //TextCapitalization.characters 将所有字母大写
          textCapitalization: TextCapitalization.characters,
          //键盘类型
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
            //内容的内边距
            contentPadding: EdgeInsets.all(10.0),
            icon: Icon(Icons.person),
            //提示文本
            labelText: '请输入你的用户名',
            helperText: '请输入注册的用户名',
          ),
          //键盘插件按钮样式
          textInputAction: TextInputAction.go,
          //设置光标样式
//          cursorColor: Colors.green,
//          cursorRadius: Radius.circular(16.0),
//          cursorWidth: 16.0,
        ),
        TextField(
          controller: passwordController,
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
            contentPadding: EdgeInsets.all(10.0),
            icon: Icon(Icons.lock),
            labelText: '请输入密码',
          ),
          obscureText: true,
        ),
        RaisedButton(
          onPressed: (){
            loginCheck();
          },
          child: Text('登录'),
        ),

        //decoration示例
//        TextField(
//          //带外边框的样式
//          decoration: InputDecoration(
//            border: OutlineInputBorder(),
//            hintText: '请输入你的用户名',
//            labelText: '用户名',
//            prefixIcon: Icon(Icons.person),
//            suffixIcon: Icon(Icons.print),
//          ),
//        ),
      ],
    );
  }

  loginCheck(){

    if(usernameController.text.length != 11){
      print('请输入正确的手机号');
    }

    if(passwordController.text.length != 6){
      print('请输入6位以上的密码');
    }
  }
}

九、Layout - 布局组件

9.1 Center-居中布局

相对居中布局,将其子 widget 居中显示在自身内部的 widget。


Center

        body:Center(
          child: Container(
            color: Colors.red,
            width: 200.0,
            height: 100.0,
            child: Center(
              child: Text(
                '居中布局',
                style: TextStyle(
                  fontSize: 36.0,
                  color: Colors.white,
                ),
              ),
            ),
          ),
        ),

9.2 Column - 垂直布局

在垂直方向上排列子widget的列表。


Column

 child: Column(

              //mainAxisAlignment属性
              //MainAxisAlignment.spaceEvenly/spaceAround/spaceBetween,
              //spaceEvenly:将主轴方向空白区域均分,使得children之间空间相等,包括首尾children
              //spaceAround:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children的空白部分为一半
              //spaceBetween:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children靠近收尾,没有空细逢
              //MainAxisAlignment.start/end/center,
              //start:将children放置在主轴起点方向
              //end:将children放置在主轴末尾方向
              //center:将children放置在主轴中间方向
              mainAxisAlignment: MainAxisAlignment.spaceBetween,

              //CrossAxisAlignment 属性
              //crossAxisAlignment: CrossAxisAlignment.center/end/start,即,根据设定的位置交叉对齐
              //center/end/start: children在交叉轴上居中/末端/起点 对齐展示
              //stretch:让children填满交叉轴方向
              //baseline:在交叉轴方向,使得于这个baseline对齐,如果主轴是垂直的,那么这个值是当作开始
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[

                //色块
                Container(
                  color: Colors.greenAccent,
                  width: 100.0,
                  height: 60.0,
                ),

                //色块
                Container(
                  color: Colors.greenAccent,
                  width: 100.0,
                  height: 60.0,
                ),

                //色块
                Container(
                  color: Colors.greenAccent,
                  width: 100.0,
                  height: 60.0,
                ),

                //色块
                Container(
                  color: Colors.greenAccent,
                  width: 100.0,
                  height: 60.0,
                ),
              ],
            ),

9.3 Row - 水平布局

在水平方向上排列子widget的列表。


Row

            child: Row(
              //mainAxisAlignment属性
              //MainAxisAlignment.spaceEvenly/spaceAround/spaceBetween,
              //spaceEvenly:将主轴方向空白区域均分,使得children之间空间相等,包括首尾children
              //spaceAround:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children的空白部分为一半
              //spaceBetween:将主轴方向空白区域均分,使得children之间空间相等,但是首尾children靠近收尾,没有空细逢
              //MainAxisAlignment.start/end/center,
              //start:将children放置在主轴起点方向
              //end:将children放置在主轴末尾方向
              //center:将children放置在主轴中间方向
              mainAxisAlignment: MainAxisAlignment.spaceBetween,

              //CrossAxisAlignment 属性
              //crossAxisAlignment: CrossAxisAlignment.center/end/start,即,根据设定的位置交叉对齐
              //center/end/start: children在交叉轴上居中/末端/起点 对齐展示
              //stretch:让children填满交叉轴方向
              //baseline:在交叉轴方向,使得于这个baseline对齐,如果主轴是垂直的,那么这个值是当作开始

              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                //色块
                Container(
                  color: Colors.orange,
                  width: 100.0,
                  height: 50.0,
                ),
                //色块
                Container(
                  color: Colors.orange,
                  width: 100.0,
                  height: 50.0,
                ),
                //色块
                Container(
                  color: Colors.orange,
                  width: 100.0,
                  height: 50.0,
                ),
              ],
            ),

十、List - 列表组件

10.1 ListBody - 列表组件

一个 widget,它沿着一个给定的轴,顺序排列它的子元素。 ListBody

class DemoPageState extends State<DemoPage> {


  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[

        //ListBody不常用,但可以和Cloumn Row及ListView结合使用即可
        ListBody(
          //对齐方式
          mainAxis: Axis.vertical,
          //内容是否反向
          reverse: false,
          children: <Widget>[
            Container(
              color: Colors.red,
              width: 50.0,
              height: 50.0,
              child: Text('A',style: TextStyle(color: Colors.white),),
            ),
            Container(
              color: Colors.orange,
              width: 50.0,
              height: 100.0,
              child: Text('B',style: TextStyle(color: Colors.white),),
            ),
            Container(
              color: Colors.blue,
              width: 50.0,
              height: 150.0,
              child: Text('C',style: TextStyle(color: Colors.white),),
            ),
          ],
        ),
      ],
    );
  }
}

10.2 ListView - 滚动列表

ListView 在任何语言中,都是占居非常重要的位置,出现的频率也相当高。可滚动的列表控件,ListView 是最常用的滚动 widget,它在滚动方向上一个接一个地显示它的孩子。在纵轴上,孩子们被要求填充 ListView。


ListView

class DemoPageState extends State<DemoPage> {
  @override
  Widget build(BuildContext context) {
//    //ListView基本用法
//    return ListView(
//      children: <Widget>[
//        //列表项
//        ListTile(
//          leading: Icon(Icons.person),
//          title: Text('A'),
//        ),
//        //列表分割线
//        Divider(height: 10.0,color: Colors.grey,),
//        ListTile(
//          leading: Icon(Icons.print),
//          title: Text('B'),
//        ),
//        Divider(height: 10.0,color: Colors.grey,),
//        ListTile(
//          leading: Icon(Icons.favorite_border),
//          title: Text('C'),
//        ),
//        Divider(height: 10.0,color: Colors.grey,),
//        ListTile(
//          leading: Icon(Icons.lock),
//          title: Text('C'),
//        ),
//        Divider(height: 10.0,color: Colors.grey,),
//
//      ],
//    );
//    return SizedBox(
//      height: 300.0,
//      child: ListView.builder(
//          //排列方向 垂直和水平
//          scrollDirection: Axis.vertical,
//          //列表项个数
//          itemCount: 10,
//          //确定每一个item的高度 会让item加载更加高效
//          itemExtent: 50.0,
//          //physics 滑动类型设置
//          //这个属性几个滑动的选择
//          //    AlwaysScrollableScrollPhysics() 总是可以滑动
//          //    NeverScrollableScrollPhysics禁止滚动
//          //    BouncingScrollPhysics 内容超过一屏 上拉有回弹效果
//          //    ClampingScrollPhysics 包裹内容 不会有回弹
//          //physics: AlwaysScrollableScrollPhysics(),
//          //    这个属性的意思就是预加载的区域
//          //    设置预加载的区域 cacheExtent 强制设置为了 0.0,从而关闭了“预加载”
//          // controller:滑动监听,我们多用于上拉加载更多,通过监听滑动的距离来执行操作
//          //在构造中默认是false primary为true时,controller滑动监听就不能使用了
//          //primary:false ,
//          // shrinkWrap child 高度会适配 item填充的内容的高度,我们非常的不希望child的高度固定,因为这样的话,
//          // 如果里面的内容超出就会造成布局的溢出。
//          //shrinkWrap: false,
//          itemBuilder: (BuildContext context, int index) {
//            return ListTile(
//              title: Text("title $index"),
//              //标题
//              leading: Icon(Icons.favorite_border),
//              //前置图标
//              subtitle: Text("sub title $index"),
//              //子标题
//              trailing: Icon(Icons.arrow_forward),
//              //后置图标
//              isThreeLine: false,
//              //是否显示三行
//              contentPadding: EdgeInsets.all(10.0),
//              //内边距
//              enabled: true,
//              //是否禁用
//              onTap: () {
//                print('点击了:$index');
//              },
//              onLongPress: () {
//                print('长按了:$index');
//              },
//              selected: false,
//            );
//          }),
//    );

//    return SizedBox(
//      height: 300.0,
//
//      //带分割线的ListView
//      child: ListView.separated(
//        //排列方向 垂直和水平
//          scrollDirection: Axis.vertical,
//          //分割线构建器
//          separatorBuilder: (BuildContext context, int index) => Divider(height: 1.0,color: Colors.grey,),
//          //列表项个数
//          itemCount: 100,
//          itemBuilder: (BuildContext context, int index) {
//            return ListTile(
//              title: Text("title $index"),
//              //标题
//              leading: Icon(Icons.favorite_border),
//              //前置图标
//              subtitle: Text("sub title $index"),
//              //子标题
//              trailing: Icon(Icons.arrow_forward),
//              //后置图标
//              isThreeLine: false,
//              //是否显示三行
//              contentPadding: EdgeInsets.all(10.0),
//              //内边距
//              enabled: true,
//              //是否禁用
//              onTap: () {
//                print('点击了:$index');
//              },
//              onLongPress: () {
//                print('长按了:$index');
//              },
//              selected: false,
//            );
//          }),
//    );

    return SizedBox(
      height: 300.0,
      //自定义列表
      child: ListView.custom(
        scrollDirection: Axis.vertical,
        //生成子项
        childrenDelegate:
            SliverChildBuilderDelegate((BuildContext context, int index) {
              //自定义容器
          return Container(
            height: 50.0,
            alignment: Alignment.center,
            color: Colors.lightBlue[100 * (index % 9)],
            child: Text('item $index'),
          );
        }, childCount: 10),
      ),
    );
  }
}


Refer