前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter 专题】28 图解 ListView/GridView 混用时滑动冲突小尝试

【Flutter 专题】28 图解 ListView/GridView 混用时滑动冲突小尝试

作者头像
阿策小和尚
发布2019-08-12 16:20:37
1.4K0
发布2019-08-12 16:20:37
举报
文章被收录于专栏:阿策小和尚

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

尝试一:CustomScrollView + sliver

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

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

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

代码语言:javascript
复制
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 情况下,只有具有足够内容的用户才能滚动视图。

代码语言:javascript
复制
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()
    ]);
  }
}

和尚的学习还很不到位,如果有不对的地方还希望多多指出。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿策小和尚 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 尝试一:CustomScrollView + sliver
  • 尝试二:primary + shrinkWrap
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档