Flutter 28: 图解 ListView/GridView

作者: 阿策神奇 | 来源:发表于2018-12-26 22:30 被阅读4次

          小菜在学习过程中会在一个 Page 页面同时用到 GridView 和 ListView 或多个 ListView,此时就会遇到常见的滑动冲突问题。小菜尝试了两种解决滑动冲突的方案,仅记录一下基本的使用方式。小菜翻译很不到位,可重点看代码。

    尝试一:CustomScrollView + sliver

          Flutter 提供了类似于 Android CollapsingToolbarLayout 的折叠效果,小菜借此了解到 CustomScrollView 这个组件,可以解决列表的滑动冲突。

          CustomScrollView 允许包含多种滚动模型,例如列表/网格和扩展标题。但其子 Widget 必须为 sliver 类型的。

          sliver 代表具有特定滚动效果的滚动模型,sliver 本身不包含滚动交互模型,需要通过 CustomScrollView 连接为一个整体。sliver 有众多具体的 Widget,小菜也在尝试过程中。

    class _ScrollPageState extends State<ScrollPage3> {
      List<int> gridData = List<int>();
    
      _setGridData() {
        for (int i = 0; i < 15; i++) {
          gridData.add(i);
        }
      }
    
      @override
      void initState() {
        _setGridData();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(appBar: AppBar(title: Text('方案一')), body: _bodyWid());
      }
    
      Widget _bodyWid() {
        return CustomScrollView(slivers: <Widget>[
          SliverList(
              delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
            return _typeTitleWid('热门分类');
          }, childCount: 1)),
          SliverPadding(padding: const EdgeInsets.all(8.0), sliver: _typeGridWid()),
          SliverList(
              delegate:
                  SliverChildBuilderDelegate((BuildContext context, int index) {
            return _typeTitleWid('智能推荐');
          }, childCount: 1)),
          _typeListWid()
        ]);
      }
    
      Widget _typeTitleWid(var titleStr) {
        return Container(
            color: Colors.white,
            child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Padding( padding: EdgeInsets.all(10.0),
                      child: Text(titleStr,
                          style:
                              TextStyle(color: Color(0xFF808080), fontSize: 14.0))),
                  Divider(color: Color(0xFF808080), height: 0.5)
                ]));
      }
    
      Widget _typeGridWid() {
        return SliverGrid(
            gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 4, mainAxisSpacing: 8.0,
                crossAxisSpacing: 8.0, childAspectRatio: 4.0),
            delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
              return Container( height: 64.0,
                  decoration: BoxDecoration(
                      color: Colors.grey, borderRadius: BorderRadius.circular(3.0)),
                  child: Center(
                      child: Text('分类 ${(index + 1)}', style: TextStyle(color: Color(0xFF333333), fontSize: 14.0))));
            }, childCount: gridData.length));
      }
    
      Widget _typeListWid() {
        return SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
              return Container(
                  child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        mainAxisSize: MainAxisSize.max,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Padding(
                              padding: EdgeInsets.all(10.0),
                              child: Text('推荐精彩内容 ${(index + 1)}',
                                  textAlign: TextAlign.left,
                                  style: TextStyle(
                                      color: Color(0xFF333333), fontSize: 15.0))),
                    Padding(
                        padding: EdgeInsets.only(top: 4.0),
                        child: Divider(color: Color(0xFF808080), height: 0.5))
                  ]));
            }, childCount: gridData.length));
      }
    }
    

    尝试二:primary + shrinkWrap

          小菜在使用 ListViewGridView 时发现有两个属性很重要。小菜的翻译很不到位,建议大家仔细阅读一下官网的介绍。

          shrinkWrap 常用于内容大小不确定情况,如果滚动视图(ListView/GridView/ScrollView 等)没有收缩包装,则滚动视图将扩展到允许的最大大小。如果是无界约束,则 shrinkWrap 必须为 true

          primary 如果为 true,即使滚动视图没有足够的内容来支撑滚动,滚动视图也是可滚动的。否则,默认为 false 情况下,只有具有足够内容的用户才能滚动视图。

    class _ScrollPageState extends State<ScrollPage3> {
      
      @override
      Widget build(BuildContext context) {
        return Scaffold(appBar: AppBar(title: Text('方案二')), body: _bodyWid2());
      }
    
      Widget _typeGridWid2() {
        return GridView.count(
            primary: false,
            shrinkWrap: true,
            crossAxisCount: 4,
            mainAxisSpacing: 8.0,
            crossAxisSpacing: 8.0,
            childAspectRatio: 4.0,
            padding: EdgeInsets.all(10.0),
            children: gridData.map((int index) {
              return Container(
                  height: 64.0,
                  decoration: BoxDecoration(
                      color: Colors.grey, borderRadius: BorderRadius.circular(3.0)),
                  child: Center(
                      child: Text('分类 ${(index + 1)}',
                          style: TextStyle(
                              color: Color(0xFF333333), fontSize: 14.0))));
            }).toList());
      }
    
      Widget _typeListWid2() {
        return ListView.separated(
            primary: false,
            shrinkWrap: true,
            itemCount: gridData.length,
            separatorBuilder: (BuildContext context, int index) => new Divider(),
            itemBuilder: (context, item) {
              return Padding(
                  padding: EdgeInsets.all(12.0),
                  child: Text('推荐精彩内容 ${(item + 1)}',
                      style: TextStyle(color: Color(0xFF333333), fontSize: 15.0)));
            });
      }
    
      Widget _bodyWid2() {
        return ListView(children: <Widget>[
          _typeTitleWid('热门分类'),
          _typeGridWid2(),
          _typeTitleWid('智能推荐'),
          _typeListWid2()
        ]);
      }
    }
    

          小菜的学习还很不到位,如果有不对的地方还希望多多指出。以下是小菜公众号,欢迎闲来吐槽~


    公众号.jpg

    相关文章

      网友评论

        本文标题:Flutter 28: 图解 ListView/GridView

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