Flutter中包含GridViews和ListViews的ListView

Posted

技术标签:

【中文标题】Flutter中包含GridViews和ListViews的ListView【英文标题】:ListView containing GridViews and ListViews in flutter 【发布时间】:2020-02-25 16:14:01 【问题描述】:

我一直在寻找实现这种设计的方法,但我不确定最好的方法是什么,我想知道如何使用 listview 和 gridview 布局这些列表(可以更改为图标按下时的列表视图),谢谢

【问题讨论】:

【参考方案1】:

我认为只为底部列表添加一个 gridview 并更改代表的 childAspectRatio (因为网格项目显然没有明确的高度)和 crossAxisCount 会做到这一点。

import 'package:flutter/material.dart';

class Tires extends StatefulWidget 
  @override
  _TiresState createState() => _TiresState();


class _TiresState extends State<Tires> 
  var _crossAxisCount = 1;
  var _childAspectRatio = 2.0;

  @override
  Widget build(BuildContext context) 
    final mediaQuery = MediaQuery.of(context);
    final titleStyle = TextStyle(fontWeight: FontWeight.bold);

    return ListView(
      children: <Widget>[
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          child: Text('Hot offer', style: titleStyle),
        ),
        SizedBox(height: 8),
        Container(
          height: mediaQuery.size.height / 4,
          child: ListView.separated(
            shrinkWrap: true,
            padding: EdgeInsets.symmetric(horizontal: 16.0),
            scrollDirection: Axis.horizontal,
            itemCount: 10,
            separatorBuilder: (_, __) => SizedBox(width: 10),
            itemBuilder: (_, __) => SizedBox(
              width: mediaQuery.size.width / 3,
              child: Card(),
            ),
          ),
        ),
        SizedBox(height: 8),
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          child: Row(
            children: <Widget>[
              Text('Hot offer', style: titleStyle),
              Spacer(),
              IconButton(
                icon: Icon(Icons.list),
                onPressed: () => setState(() 
                  _crossAxisCount = _crossAxisCount = 1;
                  _childAspectRatio = _childAspectRatio = 2.0;
                ),
              ),
              IconButton(
                icon: Icon(Icons.grid_on),
                onPressed: () => setState(() 
                  _crossAxisCount = _crossAxisCount = 2;
                  _childAspectRatio = _childAspectRatio = 1.0;
                ),
              ),
            ],
          ),
        ),
        SizedBox(height: 8),
        GridView.builder(
          primary: false,
          shrinkWrap: true,
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            childAspectRatio: _childAspectRatio,
            crossAxisSpacing: 16,
            mainAxisSpacing: 16,
            crossAxisCount: _crossAxisCount,
          ),
          itemCount: 15,
          itemBuilder: (_, __) => Card(),
        )
      ],
    );
  

【讨论】:

【参考方案2】:

您可以使用条子将所有网格和列表包含在一个滚动视图中。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget
  @override
  State<StatefulWidget> createState() 

    return _MyAppState();
  




class _MyAppState extends State<MyApp> 
 bool isGrid = true;
  @override
  Widget build(BuildContext context) 
    return MaterialApp(

      home: Scaffold(
        appBar: AppBar(title: Text('demo'),),
        body: Padding(

          child: CustomScrollView(

            slivers: <Widget>[

              SliverToBoxAdapter(
                child: Container(
                  height: 100.0,
                  child: ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: 10,
                    itemBuilder: (context, index) 
                      return Container(
                        width: 100.0,
                        child: Card(
                          child: Text('data'),
                        ),
                      );
                    ,
                  ),
                ),
              ),
              SliverToBoxAdapter(
         child: Row(
           children: <Widget>[
             Text('choose view method'),
             Row(
               children: <Widget>[
                 IconButton(icon: Icon(Icons.list), onPressed: ()
                   setState(() 
                       isGrid = false;
                   );
                 , ),

                 IconButton(icon: Icon(Icons.grid_on), onPressed: ()
                   setState(() 
                     isGrid = true;
                   );
                 , ),

               ],
             )
           ],
         ),
              ),
              ProductsWidget(
                isGrid: isGrid,
              ),

            ],
          ), padding: EdgeInsets.all(20),
        ),
      ),
    );
  


class ProductsWidget extends StatelessWidget 
  final bool isGrid;

  const ProductsWidget(Key key, this.isGrid = true) : super(key: key);
  @override
  Widget build(BuildContext context) 
    return isGrid ? SliverGrid(
      gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 200.0,
        mainAxisSpacing: 10.0,
        crossAxisSpacing: 10.0,
        childAspectRatio: 4.0,
      ),
      delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) 
          return  Container(
            width: 100.0,
            child: Card(
              child: Text('data'),
            ),
          );
        ,
        childCount: 50,
      ),
    ) :  SliverList(
        delegate: SliverChildListDelegate(
          [
            Card(child: Text('data'),),
            Card(child: Text('data'),),
            Card(child: Text('data'),),
            Card(child: Text('data'),),
          ],
        ), ) ;


  

【讨论】:

以上是关于Flutter中包含GridViews和ListViews的ListView的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 在应用程序购买中我应该在 _verifyPurchase() 中包含啥

Flutter 错误:VM 快照无效,无法从设置中推断。 - 当想要在 android 项目中包含 Flutter 模块时

flutter Column 中包含ListView高度设置问题

Flutter:在框架模块“firebase_core.FLTFirebasePlugin”中包含非模块化标头

Flutter:我们检测到您的应用在您的 1 个或多个 app bundle 或 APK 的清单文件中包含 requestLegacyExternalStorage 标志

Flutter ListVİew 总是在向上或向下滚动时重新渲染