dart Flutter如何创建ListView并根据条件显示

x3naxklr  于 2023-03-15  发布在  Flutter
关注(0)|答案(1)|浏览(148)

我列了一个清单:

List<ProductModel> productList = [
    ProductModel(name: "Oranges", price: "150"),    
    ProductModel(name: "Apples", price: "80"),
];

我想将列表显示为下面的第一个图像:

但是,我只能这样显示它:

为了只显示红色和蓝色容器一次,我应该如何更改代码?
下面是我的简化代码:

class ProductListPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _ProductListPageState();
}

class _ProductListPageState extends State<ProductListPage> {
  late StreamController<int> _postsController;
  List<ProductModel> productList = [];

  @override
  void initState() {
    _postsController = new StreamController();
    getProducts();
    super.initState();
  }

  void getProducts() {
    Fetch.getProdcuts().then((value) => {
      _postsController.add(1),
      productList.addAll(value!)
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
       body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Container(
              child: Column(
                  children: <Widget>[
                    const Text("This is a Product List"),
                  ]),
            ),
            products(),
          ],
        ),
      ),
    );
  }

  Widget products() {
    return StreamBuilder<int>(
        stream: _postsController.stream,
        builder: (BuildContext context,
            AsyncSnapshot<int> snapshot) {
          if (snapshot.hasData) {
            return productsView();
          } else {
            return Center(
              child: Text('Empty'),
            );
          }
        });
  }

  Widget productsView() {
    return ListView.builder(
        shrinkWrap: true,
        itemCount: productList.length,
        physics: NeverScrollableScrollPhysics(),
        itemBuilder: (context, index) {
          final p = productList[index];
          return  Container(
            child: Column(
                children: <Widget>[
                  Container(                        //Show this Container once
                    child: const Text('Expensive'),
                  ),
                  p.price! >= 100 ?
                    Container(
                      child: Text(p.name! + ": $" + p.price.toString()),
                    )
                    : Container(),
                  const SizedBox(                   //Show this SizedBox once
                    height: 30.0,
                  ),
                  Container(                        //Show this Container once
                    child: const Text('Cheap'),
                  ),
                  p.price! < 100 ?
                    Container(
                      child: Text(p.name! + ": $" + p.price.toString()),
                    )
                    : Container(),
                ]),
          );
        });
  }
}

class ProductModel extends Object {
  String? name;
  double? price;

  ProductModel({this.name, this.price});

  ProductModel.fromJson(Map<String, dynamic> json) {
    name = json["name"];
    price = json["price"];
  }

  Map<String, dynamic> toJson() => {
    'name': name,
    'price': price,
  };
}

我尝试添加一个bool变量,并在ExpensiveCheap容器显示后将其更改为true,但没有效果。我想我应该更改整个列表的结构,但似乎找不到正确的方法。有什么建议吗?

lf5gs5x2

lf5gs5x21#

不要使用一个ListView.builder,而是使用两个。插入逻辑,用于当您将产品列表分为便宜和昂贵时,如下所示:

void getProducts() {
  Fetch fetch = Fetch();
  fetch.getProdcuts().then((value) {
    _postsController.add(1);
    debugPrint(value.toString());
    for (var item in value) {
      debugPrint(item.toString());
      final price = double.parse(item["product"]["price"]);
      final name = item["product"]["name"];
      final json = {"name": name, "price": price};
      final product = ProductModel.fromJson(json);
      if (price >= 100) {
        expensiveProductList.add(product);
      } else {
        cheapProductList.add(product);
      }
    }
  });
}

然后在productView中,用标题和两个列表(便宜和昂贵)创建一个列。也就是说,标题只显示一次,然后你就得到了填充的列表。下面是一个可能的示例:

Widget productsView() {
  return Column(children: [
    Container(
      //Show this Container once
      child: const Text('Expensive'),
    ),
    Expanded(
        child: ListView.builder(
            itemCount: expensiveProductList.length,
            itemBuilder: (context, index) {
              final p = expensiveProductList[index];
              return Container(
                child: Text("${p.name!}: ${p.price.toString()}"),
              );
            })),
    Container(
      // Show this Container once
      child: const Text('Cheap'),
    ),
    Expanded(
        child: ListView.builder(
            itemCount: cheapProductList.length,
            itemBuilder: (context, index) {
              final p = cheapProductList[index];
              return Container(
                child: Text("${p.name!}: ${p.price.toString()}"),
              );
            })),
  ]);
}

上面的代码可能会有一些问题,因为它被简化了,但是你应该能够遵循类似的格式来实现你想要的。

完整示例

class ProductListPage extends StatefulWidget {
  const ProductListPage({super.key});

  @override
  State<StatefulWidget> createState() => _ProductListPageState();
}

class _ProductListPageState extends State<ProductListPage> {
  late StreamController<int> _postsController;
  List<ProductModel> cheapProductList = [];
  List<ProductModel> expensiveProductList = [];

  @override
  void initState() {
    _postsController = StreamController();
    getProducts();
    super.initState();
  }

  void getProducts() {
    fetch.getProdcuts().then((value) {
      _postsController.add(1);
      debugPrint(value.toString());
      for (var item in value) {
        debugPrint(item.toString());
        final price = double.parse(item["product"]["price"]);
        final name = item["product"]["name"];
        final json = {"name": name, "price": price};
        final product = ProductModel.fromJson(json);
        if (price >= 100) {
          expensiveProductList.add(product);
        } else {
          cheapProductList.add(product);
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(child: products()),
    );
  }

  Widget products() {
    return StreamBuilder<int>(
        stream: _postsController.stream,
        builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
          if (snapshot.hasData) {
            return productsView();
          } else {
            return Center(
              child: Text('Empty'),
            );
          }
        });
  }

  Widget productsView() {
    return Column(mainAxisSize: MainAxisSize.min, children: [
      Container(
        //Show this Container once
        child: const Text('Expensive'),
      ),
      Flexible(
          child: ListView.builder(
              shrinkWrap: true,
              itemCount: expensiveProductList.length,
              itemBuilder: (context, index) {
                final p = expensiveProductList[index];
                return Container(
                  child: Text("${p.name}: ${p.price.toString()}"),
                );
              })),
      Container(
        // Show this Container once
        child: const Text('Cheap'),
      ),
      Flexible(
          child: ListView.builder(
              shrinkWrap: true,
              itemCount: cheapProductList.length,
              itemBuilder: (context, index) {
                final p = cheapProductList[index];
                return Container(
                  child: Text("${p.name}: ${p.price.toString()}"),
                );
              })),
    ]);
  }
}

相关问题