基于按钮点击刷新列表视图
Refresh listview based on button click
我有一个类别和产品列表。我希望当我点击一个类别时:
- 所选类别应将颜色更改为橙色。
- 应使用所选类别的产品刷新产品列表视图。
我尝试添加 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),
)
],
)
],
),
),
),
),
),
);
}
}
我有一个类别和产品列表。我希望当我点击一个类别时:
- 所选类别应将颜色更改为橙色。
- 应使用所选类别的产品刷新产品列表视图。
我尝试添加 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),
)
],
)
],
),
),
),
),
),
);
}
}