如何通过使用 json API 在列表视图中创建网格视图

tet*_*kil 3 api json dart flutter

我想创建一个购物车应用

我有问题

如何使用 JSON API 在 ListView 中创建 GridView

我想要它完全像这个例子:

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

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

- - 更新 - -

关于 SliverGrid

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

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)".
Run Code Online (Sandbox Code Playgroud)

关于 ListView (它工作正常)..

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());
                          }
                        }),
                  ),
                ),
              ],
            ),
          )
        ]));
  }
}
Run Code Online (Sandbox Code Playgroud)

che*_*ins 5

您不能GridView直接将 a 嵌入到 a中,ListView除非您使用为GridView. 如果您想保持图像中显示的两个部分的滚动,最好的方法是使用 aCustomScrollViewSlivers

图像后是我的建议。

在此处输入图片说明

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,
            ),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您想从网络中检索 json,您可以添加/替换以下代码。添加一个返回 a 的方法,Future然后ListView使用 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());
                        }
                      }),
                ),
              ),
    ....
Run Code Online (Sandbox Code Playgroud)