基于按钮点击刷新列表视图

Refresh listview based on button click

我有一个类别和产品列表。我希望当我点击一个类别时:

  1. 所选类别应将颜色更改为橙​​色。
  2. 应使用所选类别的产品刷新产品列表视图。

我尝试添加 setState 并尝试更改颜色和列表视图,但这没有用。我有什么想法需要纠正吗?

  Future fetchProducts() async {
    return await Provider.of<Products>(context, listen: false)
        .fetchAndSetProducts('title', false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        backgroundColor: Colors.grey[100],
        elevation: 0,
        brightness: Brightness.light,
        leading: Icon(null),
        actions: <Widget>[
          IconButton(
            onPressed: () {},
            icon: Icon(
              Icons.shopping_basket,
              color: Colors.grey[800],
            ),
          )
        ],
      ),
      body: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
                padding: EdgeInsets.symmetric(horizontal: 10.0),
                child: FutureBuilder(
                    future: _screenFuture,
                    // ignore: missing_return
                    builder: (context, snap) {
                      if (snap.error != null &&
                          !snap.error
                              .toString()
                              .contains('NoSuchMethodError')) {
                        return Center(child: Text('Something went wrong!'));
                      } else if (snap.hasData) {
                        var categoriesData = Provider.of<Categories>(context);
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            FadeAnimation(
                                1,
                                Text(
                                  'Food Delivery',
                                  style: TextStyle(
                                      color: Colors.grey[80],
                                      fontWeight: FontWeight.bold,
                                      fontSize: 30),
                                )),
                            SizedBox(
                              height: 20,
                            ),
                            Container(
                                height: 50,
                                child: ListView.builder(
                                    scrollDirection: Axis.horizontal,
                                    itemCount: categoriesData.items.length,
                                    itemBuilder: (ctx, i) => FadeAnimation(
                                        i.toDouble(),
                                        makeCategory(
                                            isActive: i.toDouble() == 0
                                                ? true
                                                : false,
                                            title: categoriesData.items
                                                .toList()[i]
                                                .title)))),
                            SizedBox(
                              height: 10,
                            ),
                          ],
                        );
                      } else if (snap.connectionState ==
                          ConnectionState.waiting) {
                        //return Container();
                        return Center(child: Spinner());
                      }
                    })),
            Padding(
                padding: EdgeInsets.symmetric(horizontal: 20.0),
                child: FutureBuilder(
                    future: _productScreenFuture,
                    // ignore: missing_return
                    builder: (context, snap) {
                      if (snap.error != null &&
                          !snap.error
                              .toString()
                              .contains('NoSuchMethodError')) {
                        return Center(child: Text('Something went wrong!'));
                      } else if (snap.hasData) {
                        productsData = Provider.of<Products>(context);
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            FadeAnimation(
                                1,
                                Text(
                                  'Food Delivery',
                                  style: TextStyle(
                                      color: Colors.grey[80],
                                      fontWeight: FontWeight.bold,
                                      fontSize: 30),
                                )),
                            SizedBox(
                              height: 20,
                            ),
                            SizedBox(
                                height: 300,
                                child: ListView.builder(
                                    shrinkWrap: true,
                                    scrollDirection: Axis.horizontal,
                                    itemCount: productsData.items.length,
                                    itemBuilder: (ctx, i) => FadeAnimation(
                                        1.4,
                                        makeItem(
                                            image: 'assets/images/one.jpg',
                                            title: productsData.items[i].title,
                                            price:
                                                productsData.items[i].price)))),
                            SizedBox(
                              height: 10,
                            ),
                          ],
                        );
                      } else if (snap.connectionState ==
                          ConnectionState.waiting) {
                        //return Container();
                        return Center(child: Spinner());
                      }
                    })),
            SizedBox(
              height: 30,
            )
          ],
        ),
      ),
    );
  }

  Widget makeCategory({isActive, title}) {
    return AspectRatio(
        aspectRatio: isActive ? 3 : 2.5 / 1,
        child: GestureDetector(
          onTap: () {
            print(title + " clicked");
            setState(() {
              isActive = true;
              productsData = Provider.of<Products>(context, listen: false)
                  .findBycategoryName(title);
              print(productsData.first.title); // << data is available
            });
          },
          child: Container(
            margin: EdgeInsets.only(right: 10),
            decoration: BoxDecoration(
              color: isActive ? Colors.yellow[700] : Colors.white,
              borderRadius: BorderRadius.circular(50),
            ),
            child: Align(
              child: Text(
                title,
                style: TextStyle(
                    color: isActive ? Colors.white : Colors.grey[500],
                    fontSize: 18,
                    fontWeight: isActive ? FontWeight.bold : FontWeight.w100),
              ),
            ),
          ),
        ));
  }

  Widget makeItem({image, String title, double price}) {
    return AspectRatio(
      aspectRatio: 1 / 1.5,
      child: GestureDetector(
        child: Container(
          margin: EdgeInsets.only(right: 20),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(20),
              image: DecorationImage(
                image: AssetImage(image),
                fit: BoxFit.cover,
              )),
          child: Container(
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(20),
                gradient: LinearGradient(begin: Alignment.bottomCenter, stops: [
                  .2,
                  .9
                ], colors: [
                  Colors.black.withOpacity(.9),
                  Colors.black.withOpacity(.3),
                ])),
            child: //Expanded(
                Padding(
              padding: EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Align(
                    alignment: Alignment.topRight,
                    child: Icon(
                      Icons.favorite,
                      color: Colors.white,
                    ),
                  ),
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Text(
                        "\Tsh. $price",
                        style: TextStyle(
                            color: Colors.white,
                            fontSize: 20,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      Text(
                        title,
                        style: TextStyle(color: Colors.white, fontSize: 20),
                      )
                    ],
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

isActive 不是变量,当您在 setState 中更改它时,什么也不会发生。尝试使用 int? index 变量来保存您选择的类别索引

实际上,当您调用 setState() 时,由于以下代码,您的 isActive 再次更改为 false:

makeCategory(
  isActive: i.toDouble() == 0
  ? true
  : false,

试试这个代码:

 bool currentCategory = 0;

 Future fetchProducts() async {
return await Provider.of<Products>(context, listen: false)
    .fetchAndSetProducts('title', false);


}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        backgroundColor: Colors.grey[100],
        elevation: 0,
        brightness: Brightness.light,
        leading: Icon(null),
        actions: <Widget>[
          IconButton(
            onPressed: () {},
            icon: Icon(
              Icons.shopping_basket,
              color: Colors.grey[800],
            ),
          )
        ],
      ),
      body: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
                padding: EdgeInsets.symmetric(horizontal: 10.0),
                child: FutureBuilder(
                    future: _screenFuture,
                    // ignore: missing_return
                    builder: (context, snap) {
                      if (snap.error != null &&
                          !snap.error
                              .toString()
                              .contains('NoSuchMethodError')) {
                        return Center(child: Text('Something went wrong!'));
                      } else if (snap.hasData) {
                        var categoriesData = Provider.of<Categories>(context);
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            FadeAnimation(
                                1,
                                Text(
                                  'Food Delivery',
                                  style: TextStyle(
                                      color: Colors.grey[80],
                                      fontWeight: FontWeight.bold,
                                      fontSize: 30),
                                )),
                            SizedBox(
                              height: 20,
                            ),
                            Container(
                                height: 50,
                                child: ListView.builder(
                                    scrollDirection: Axis.horizontal,
                                    itemCount: categoriesData.items.length,
                                    itemBuilder: (ctx, i) => FadeAnimation(
                                        i.toDouble(),
                                        makeCategory(
                                            isActive: i == currentCategory 
                                                ? true
                                                : false,
                                            position: i,
                                            title: categoriesData.items
                                                .toList()[i]
                                                .title)))),
                            SizedBox(
                              height: 10,
                            ),
                          ],
                        );
                      } else if (snap.connectionState ==
                          ConnectionState.waiting) {
                        //return Container();
                        return Center(child: Spinner());
                      }
                    })),
            Padding(
                padding: EdgeInsets.symmetric(horizontal: 20.0),
                child: FutureBuilder(
                    future: _productScreenFuture,
                    // ignore: missing_return
                    builder: (context, snap) {
                      if (snap.error != null &&
                          !snap.error
                              .toString()
                              .contains('NoSuchMethodError')) {
                        return Center(child: Text('Something went wrong!'));
                      } else if (snap.hasData) {
                        productsData = Provider.of<Products>(context);
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisSize: MainAxisSize.min,
                          children: <Widget>[
                            FadeAnimation(
                                1,
                                Text(
                                  'Food Delivery',
                                  style: TextStyle(
                                      color: Colors.grey[80],
                                      fontWeight: FontWeight.bold,
                                      fontSize: 30),
                                )),
                            SizedBox(
                              height: 20,
                            ),
                            SizedBox(
                                height: 300,
                                child: ListView.builder(
                                    shrinkWrap: true,
                                    scrollDirection: Axis.horizontal,
                                    itemCount: productsData.items.length,
                                    itemBuilder: (ctx, i) => FadeAnimation(
                                        1.4,
                                        makeItem(
                                            image: 'assets/images/one.jpg',
                                            title: productsData.items[i].title,
                                            price:
                                                productsData.items[i].price)))),
                            SizedBox(
                              height: 10,
                            ),
                          ],
                        );
                      } else if (snap.connectionState ==
                          ConnectionState.waiting) {
                        //return Container();
                        return Center(child: Spinner());
                      }
                    })),
            SizedBox(
              height: 30,
            )
          ],
        ),
      ),
    );
  }

  Widget makeCategory({isActive, title, position}) {
    return AspectRatio(
        aspectRatio: isActive ? 3 : 2.5 / 1,
        child: GestureDetector(
          onTap: () {
            print(title + " clicked");
            setState(() {
              currentCategory = position;
              productsData = Provider.of<Products>(context, listen: false)
                  .findBycategoryName(title);
              print(productsData.first.title); // << data is available
            });
          },
          child: Container(
            margin: EdgeInsets.only(right: 10),
            decoration: BoxDecoration(
              color: isActive ? Colors.yellow[700] : Colors.white,
              borderRadius: BorderRadius.circular(50),
            ),
            child: Align(
              child: Text(
                title,
                style: TextStyle(
                    color: isActive ? Colors.white : Colors.grey[500],
                    fontSize: 18,
                    fontWeight: isActive ? FontWeight.bold : FontWeight.w100),
              ),
            ),
          ),
        ));
  }

  Widget makeItem({image, String title, double price}) {
    return AspectRatio(
      aspectRatio: 1 / 1.5,
      child: GestureDetector(
        child: Container(
          margin: EdgeInsets.only(right: 20),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(20),
              image: DecorationImage(
                image: AssetImage(image),
                fit: BoxFit.cover,
              )),
          child: Container(
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(20),
                gradient: LinearGradient(begin: Alignment.bottomCenter, stops: [
                  .2,
                  .9
                ], colors: [
                  Colors.black.withOpacity(.9),
                  Colors.black.withOpacity(.3),
                ])),
            child: //Expanded(
                Padding(
              padding: EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Align(
                    alignment: Alignment.topRight,
                    child: Icon(
                      Icons.favorite,
                      color: Colors.white,
                    ),
                  ),
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Text(
                        "\Tsh. $price",
                        style: TextStyle(
                            color: Colors.white,
                            fontSize: 20,
                            fontWeight: FontWeight.bold),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      Text(
                        title,
                        style: TextStyle(color: Colors.white, fontSize: 20),
                      )
                    ],
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}