如何在颤动的列内使用 StaggeredGridView?

Posted

技术标签:

【中文标题】如何在颤动的列内使用 StaggeredGridView?【英文标题】:How to use StaggeredGridView inside Column in flutter? 【发布时间】:2021-03-14 03:06:01 【问题描述】:

我的代码在 Column 中不使用 StaggeredGridView.count() 时运行良好。谁能帮我吗 ?我是 Flutter 的新手!

import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'smooth_star_rating.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

void main() => runApp(MaterialApp(
      theme: ThemeData(primaryColor: Colors.black),
      home: Home(),
    ));

class Home extends StatelessWidget 
  Container TopArtist(String imageVal, String heading, double count) 
    return Container(
      width: 200,
      child: Card(
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(15.0))),
        color: Color(0xFFf2630a),
        child: Wrap(
          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: ClipOval(
                child: Center(
                  child: Material(
                    elevation: 4.0,
                    shape: CircleBorder(),
                    clipBehavior: Clip.hardEdge,
                    color: Colors.transparent,
                    child: Ink.image(
                      image: AssetImage(imageVal),
                      padding: const EdgeInsets.all(8.0),
                      fit: BoxFit.cover,
                      width: 160.0,
                      height: 160.0,
                      child: InkWell(
                        onTap: () ,
                      ),
                    ),
                  ),
                ),
              ),
            ),
            ListTile(
              title: Text(
                heading,
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.white, fontFamily: 'Mulish'),
              ),
              subtitle: Center(
                child: SmoothStarRating(
                  allowHalfRating: true,
                  starCount: 5,
                  rating: count,
                  size: 20,
                  color: Colors.black,
                  borderColor: Colors.white,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  

  Material MyItems(IconData icon, String heading, int color) 
    return Material(
      color: Colors.white,
      elevation: 14.0,
      shadowColor: Color(0x802196F3),
      borderRadius: BorderRadius.circular(24.0),
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      heading,
                      style: TextStyle(color: new Color(color), fontSize: 20),
                    ),
                  ),
                  Material(
                    color: new Color(color),
                    borderRadius: BorderRadius.circular(24.0),
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Icon(
                        icon,
                        color: Colors.white,
                        size: 30.0,
                      ),
                    ),
                  ),
                ],
              )
            ],
          ),
        ),
      ),
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text("Project Title", style: TextStyle(color: Color(0xFFf2630a))),
        backgroundColor: Colors.white,
      ),
      body: Column(
        children: [
          Container(
            color: Colors.grey[300],
            child: Column(
              children: [
                Container(
                  color: Color(0xFFf2630a),
                  child: Padding(
                    padding: const EdgeInsets.all(18.0),
                    child: TextField(
                      decoration: InputDecoration(
                          fillColor: Colors.white,
                          filled: true,
                          border: InputBorder.none,
                          suffixIcon: Icon(Icons.search),
                          hintText: 'What are you looking for ?'),
                    ),
                  ),
                ),
                Container(
                  child: Padding(
                    padding: const EdgeInsets.all(12.0),
                    child: Text(
                      "Top Artist",
                      style: TextStyle(color: Color(0xFFf2630a), fontSize: 25),
                    ),
                  ),
                ),
                Container(
                  child: Divider(
                    color: Colors.black,
                    height: 20,
                    thickness: 3,
                    indent: 180,
                    endIndent: 180,
                  ),
                ),
                Container(
                  padding: EdgeInsets.symmetric(vertical: 20),
                  height: 300,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: [
                      TopArtist("assets/avatar.jpg", "Heading", 3),
                      TopArtist("assets/avatar.jpg", "Heading", 4),
                      TopArtist("assets/avatar.jpg", "Heading", 5),
                      TopArtist("assets/avatar.jpg", "Heading", 1),
                      TopArtist("assets/avatar.jpg", "Heading", 2),
                      TopArtist("assets/avatar.jpg", "Heading", 5),
                    ],
                  ),
                ),
              ],
            ),
          ),
          Container(
            child: Column(
              children: [
                Container(
                  child: Padding(
                    padding: const EdgeInsets.all(12.0),
                    child: Text(
                      "Categories",
                      style: TextStyle(color: Color(0xFFf2630a), fontSize: 25),
                    ),
                  ),
                ),
                Container(
                  child: Divider(
                    color: Colors.black,
                    height: 20,
                    thickness: 3,
                    indent: 180,
                    endIndent: 180,
                  ),
                ),
                Container(
                  child: Expanded(
                    child: StaggeredGridView.count(
                      crossAxisCount: 2,
                      crossAxisSpacing: 12.0,
                      mainAxisSpacing: 12.0,
                      padding:
                          EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
                      children: [
                        MyItems(Icons.graphic_eq, "TotalViews", 0xffed622b),
                        MyItems(Icons.graphic_eq, "TotalViews", 0xffed622b),
                        MyItems(Icons.graphic_eq, "TotalViews", 0xffed622b),
                        MyItems(Icons.graphic_eq, "TotalViews", 0xffed622b),
                        MyItems(Icons.graphic_eq, "TotalViews", 0xffed622b),
                        MyItems(Icons.graphic_eq, "TotalViews", 0xffed622b),
                      ],
                      staggeredTiles: [
                        StaggeredTile.extent(1, 130),
                        StaggeredTile.extent(1, 130),
                        StaggeredTile.extent(1, 130),
                        StaggeredTile.extent(1, 130),
                        StaggeredTile.extent(1, 130),
                        StaggeredTile.extent(1, 130),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  


【问题讨论】:

【参考方案1】:

您必须将 Column 放在 Material() 小部件中,并添加非常重要的属性 shrinkWrap: true,physics: NeverScrollableScrollPhysics(),

下面的完整示例:

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

Future<List<String>> _getPictures() async 
  /// replace with your async query to your REST api.
  return [
    'https://apod.nasa.gov/apod/image/0708/hh49_spitzer_c29.jpg',
    'https://apod.nasa.gov/apod/image/1507/trifid_spitzerR1024.jpg',
    'https://apod.nasa.gov/apod/image/1409/rippledsky_dai_960.jpg'
  ];


class StaggeredInsideColumn extends StatefulWidget 
  const StaggeredInsideColumn(
    Key? key,
  ) : super(key: key);

  @override
  _StaggeredInsideColumnState createState() => _StaggeredInsideColumnState();


class _StaggeredInsideColumnState extends State<StaggeredInsideColumn> 
  late final Future<List<String>> _pictureUrlList;

  @override
  void initState() 
    super.initState();
    _pictureUrlList = _getPictures();
  

  @override
  Widget build(BuildContext context) 
    return SingleChildScrollView(
        child: Material(
            child: Column(children: [
      Text('hello world'),

      /// ... your other column items

      FutureBuilder<List<String>>(
          future: _pictureUrlList,
          builder: (context, AsyncSnapshot<List<String>> snapshot) 
            if (snapshot.connectionState == ConnectionState.done &&
                snapshot.hasData) 
              List<String> pictures = snapshot.data!;
              return StaggeredGridView.countBuilder(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                crossAxisCount: 3,
                itemCount: snapshot.data!.length,
                itemBuilder: (BuildContext context, int index) => Container(
                  child: Image.network(
                    pictures[index],
                    fit: BoxFit.fitWidth,
                  ),
                ),
                staggeredTileBuilder: (int index) 
                  int tileCount = index % 7 == 0 ? 2 : 1;
                  return StaggeredTile.count(tileCount, tileCount);
                ,
                mainAxisSpacing: 8.0,
                crossAxisSpacing: 8.0,
              );
             else
              return CircularProgressIndicator();
          )
    ])));
  

【讨论】:

【参考方案2】: 按照官方文档很简单: SingleChildScrollView(孩子: 材料( 孩子:列( 孩子们: [ 容器( 孩子:新的 StaggeredGridView.countBuilder( 交叉轴计数:4, 项目数:8, 收缩包装:是的, 物理:NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) => new Container( 颜色:颜色。绿色, 孩子:新中心( 孩子:新的CircleAvatar( 背景颜色:颜色.白色, 孩子:新文本('$index'), ), )), staggeredTileBuilder: (int index) => 新的 StaggeredTile.count(2, index.isEven ? 2 : 1), 主轴间距:4.0, 交叉轴间距:4.0, ), ) ] ) ) )

【讨论】:

以上是关于如何在颤动的列内使用 StaggeredGridView?的主要内容,如果未能解决你的问题,请参考以下文章

在垂直列表视图中颤动动态高度水平列表视图

如何使垂直条颤动,如图所示

基于字母的列内字母数字值的分离

列内的列不会填充宽度

一个字段的列内带有下拉菜单的材料 UI 表

Pandas - 在数据框中的列内扩展嵌套的 json 数组