如何使用json API在Flutter中在列表视图中创建gridview [英] How to create a gridview within a listview by flutter with json API

查看:188
本文介绍了如何使用json API在Flutter中在列表视图中创建gridview的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个购物车应用程序

I'd like to create a shopping cart app

我遇到了问题

如何使用JSON API通过Flutter创建ListView中的GridView

How to create a GridView within a ListView by flutter with JSON API

我希望它完全像下面的示例:

I want it exactly like this Example :

https://i.stack.imgur.com/2KQFG.png

https://i.stack.imgur.com/I0gY8.gif

关于SliverGrid

我试图获取产品,但是出现了错误(这与SliverGrid部分有关)

I tried to fetch the products but an error appeared (This is regarding the SliverGrid part)

I/flutter ( 5992): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5992): The following assertion was thrown building FutureBuilder<List<dynamic>>(dirty, state:
I/flutter ( 5992): _FutureBuilderState<List<dynamic>>#78747):
I/flutter ( 5992): A build function returned null.
I/flutter ( 5992): The offending widget is: FutureBuilder<List<dynamic>>
I/flutter ( 5992): Build functions must never return null. To return an empty space that causes the building widget to
I/flutter ( 5992): fill available room, return "new Container()". To return an empty space that takes as little room as
I/flutter ( 5992): possible, return "new Container(width: 0.0, height: 0.0)".

关于ListView(工作正常).

With regard to ListView (It works fine)..

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';

Future<List<dynamic>> getCategoriesApi() async {
  http.Response response1 =
      await http.get("http://159.89.228.206/");
  Map<String, dynamic> decodedCategories = json.decode(response1.body);
  //print(response1);
  return decodedCategories['categories'];
}

Future<List<dynamic>> getProductsApi() async {
  http.Response response =
      await http.get("http://159.89.228.206/");
  Map<String, dynamic> decodedCategories2 = json.decode(response.body);
  // print(response);
  return decodedCategories2['last'];
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(title: 'Sliver Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ScrollController _scrollController = new ScrollController();

  List<dynamic> products;
  List<dynamic> categories;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text(widget.title),
        ),
        body: Column(children: <Widget>[
          Expanded(
            child: CustomScrollView(
              controller: _scrollController,
              slivers: <Widget>[
                SliverToBoxAdapter(
                  child: SizedBox(
                    height: 120.0,
                    child: FutureBuilder(
                        future: getCategoriesApi(),
                        builder: (BuildContext context,
                            AsyncSnapshot<List<dynamic>> snapshot) {
                          if (snapshot.connectionState ==
                              ConnectionState.done) {
                            return ListView.builder(
                              scrollDirection: Axis.horizontal,
                              itemBuilder: (context, index) {
                                Map<String, String> category =
                                    snapshot.data[index].cast<String, String>();
                                return Card(
                                  child: Container(
                                    height: double.infinity,
                                    color: Colors.grey[200],
                                    child: Center(
                                      child: Padding(
                                        padding: EdgeInsets.all(30.0),
                                        child: Text(category["name"]),
                                      ),
                                    ),
                                  ),
                                );
                              },
                              itemCount: snapshot.data.length,
                            );
                          } else {
                            return Center(child: CircularProgressIndicator());
                          }
                        }),
                  ),
                ),
                SliverToBoxAdapter(
                  child: Container(
                    child: FutureBuilder(
                        future: getProductsApi(),
                        builder: (BuildContext context,
                            AsyncSnapshot<List<dynamic>> snapshot) {
                          if (snapshot.connectionState ==
                              ConnectionState.done) {
                            SliverGrid(
                              gridDelegate:
                                  SliverGridDelegateWithFixedCrossAxisCount(
                                crossAxisCount: 2,
                                childAspectRatio: 0.8,
                              ),
                              delegate: SliverChildBuilderDelegate(
                                (context, index) {
                                  Map<String, String> product = snapshot
                                      .data[index]
                                      .cast<String, String>();

                                  return Card(
                                    child: Container(
                                      height: double.infinity,
                                      color: Colors.grey[200],
                                      child: Center(
                                        child: Padding(
                                          padding: EdgeInsets.all(30.0),
                                          child: Text(product["name"]),
                                        ),
                                      ),
                                    ),
                                  );
                                },
                                childCount: snapshot.data.length,
                              ),
                            );
                          } else {
                            return Center(child: CircularProgressIndicator());
                          }
                        }),
                  ),
                ),
              ],
            ),
          )
        ]));
  }
}

推荐答案

除非您使用为GridView保留的高度,否则不能将GridView直接嵌入到ListView中.如果要在图像中显示时都保持两个部分的滚动,最好的方法是使用CustomScrollViewSlivers.

You can't embed a GridView directly in a ListView unless you play with the height reserved for the GridView. If you want to maintain the scroll for both sections as you show in your images, the best thing is to use a CustomScrollView and Slivers.

图片是我的提议之后.

import 'dart:convert';

import 'package:flutter/material.dart';

String productsJson =
    '{"last": [{"product_id":"62","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}, '
    '{"product_id":"61","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}, '
    '{"product_id":"57","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}, '
    '{"product_id":"63","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}, '
    '{"product_id":"64","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}, '
    '{"product_id":"58","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}, '
    '{"product_id":"59","thumb":"sandwich.png","name":"Test Tilte","price":"\$55.00"}]}';

String categoriesJson = '{"categories":['
    '{"name":"Category 1","image":"icon.png","id":2}, '
    '{"name":"Category 2","image":"icon.png","id":4}, '
    '{"name":"Category 3","image":"icon.png","id":4}, '
    '{"name":"Category 4","image":"icon.png","id":4}, '
    '{"name":"Category 5","image":"icon.png","id":6}]}';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(title: 'Sliver Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ScrollController _scrollController = ScrollController();

  List<dynamic> products;
  List<dynamic> categories;

  @override
  initState() {
    super.initState();

    Map<String, dynamic> decoded = json.decode(productsJson);
    products = decoded['last'];

    Map<String, dynamic> decodedCategories = json.decode(categoriesJson);
    categories = decodedCategories['categories'];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: CustomScrollView(
        controller: _scrollController,
        slivers: <Widget>[
          SliverToBoxAdapter(
            child: SizedBox(
              height: 120.0,
              child: ListView.builder(
                scrollDirection: Axis.horizontal,
                itemBuilder: (context, index) {
                  Map<String, String> category =
                      categories[index].cast<String, String>();
                  return Card(
                    child: Container(
                      height: double.infinity,
                      color: Colors.grey[200],
                      child: Center(
                        child: Padding(
                          padding: EdgeInsets.all(30.0),
                          child: Text(category["name"]),
                        ),
                      ),
                    ),
                  );
                },
                itemCount: categories.length,
              ),
            ),
          ),
          SliverGrid(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 0.8,
            ),
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                Map<String, String> product =
                    products[index].cast<String, String>();
                return Card(
                  child: Container(
                    color: Colors.grey[400],
                    child: Padding(
                      padding: EdgeInsets.symmetric(vertical: 30.0),
                      child: Center(
                          child: Text("Product ${product["product_id"]}")),
                    ),
                  ),
                );
              },
              childCount: products.length,
            ),
          ),
        ],
      ),
    );
  }
}

如果要从网络中检索json,可以添加/替换以下代码.添加一个返回Future的方法,然后使用FutureBuilder构建ListView.

If you want to retrieve the json from the network you can add/replace the following code. Add a method that returns a Future and then build the ListView using a FutureBuilder.

....
import 'package:http/http.dart' as http;
import 'dart:async';
....
      Future<List<dynamic>> getCategories() async {
        http.Response response = await http.get("http://159.89.228.206");
        Map<String, dynamic> decodedCategories = json.decode(response.body);
        return decodedCategories['categories'];
      }
    ...
    ...
              SliverToBoxAdapter(
                child: SizedBox(
                  height: 120.0,
                  child: FutureBuilder(
                      future: getCategories(),
                      builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
                        if (snapshot.connectionState == ConnectionState.done) {
                          return ListView.builder(
                            scrollDirection: Axis.horizontal,
                            itemBuilder: (context, index) {
                              Map<String, String> category =
                                  snapshot.data[index].cast<String, String>();
                              return Card(
                                child: Container(
                                  height: double.infinity,
                                  color: Colors.grey[200],
                                  child: Center(
                                    child: Padding(
                                      padding: EdgeInsets.all(30.0),
                                      child: Text(category["name"]),
                                    ),
                                  ),
                                ),
                              );
                            },
                            itemCount: snapshot.data.length,
                          );
                        } else {
                          return Center(child: CircularProgressIndicator());
                        }
                      }),
                ),
              ),
    ....

这篇关于如何使用json API在Flutter中在列表视图中创建gridview的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆