我想知道如何在 GridView.builder 中更新 Widget。 我在 GestureDetector 的 onTap 调用时使用了 setState(),但 Gridview.Builder 项目中的小部件没有改变。
这是改变状态的函数
Widget todayProductCard(String url, String name, String price, String mall,
String discount, String imageURL, String like) {
bool _isSelected = false;
if (name.length >= 15) {
name = name.substring(0, 15) + "...";
}
return GestureDetector(
onTap: () {
setState(() {
_isSelected = !_isSelected;
print(_isSelected.toString() + " " + name);
});
},
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Stack(
children: [
Image.network(
imageURL,
width: MediaQuery.of(context).size.width / 2.2,
height: MediaQuery.of(context).size.height / 4.5,
fit: BoxFit.cover,
),
Visibility(
visible: _isSelected,
这是 build()(_productWidgetList 是上面的函数列表)
@override
Widget build(BuildContext context) {
print("qkwueiuqoieuqoieuoiqueoique");
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 30,
),
child: Icon(Icons.more_horiz),
)
],
// title: Text(widget.closetName),
title: Text(toggle.toString()),
centerTitle: true,
brightness: Brightness.light,
),
body: FutureBuilder(
future: productList(widget.userID, widget.closetName),
builder: (BuildContext context,
AsyncSnapshot<List<ProductModel>> snapshot) {
if (snapshot.hasData) {
return GridView.builder(
padding: EdgeInsets.fromLTRB(
12,
0,
12,
0,
),
shrinkWrap: true,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.7,
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
return _productWidgetList[index];
},
);
} else {
return Container();
}
}),
);
}
}
这是完整的代码
class FavoriteEditScreen extends StatefulWidget {
const FavoriteEditScreen({Key key, this.userID, this.closetName})
: super(key: key);
final String userID;
final String closetName;
@override
_FavoriteEditScreenState createState() => _FavoriteEditScreenState();
}
class _FavoriteEditScreenState extends State<FavoriteEditScreen> {
ProductComponent productComponent = new ProductComponent();
bool futureSemaphore = true;
int httpPageNum = 1;
String appbarString = "appbarString";
List<Widget> _productWidgetList = [];
Future<List<ProductModel>> productList(
String userID, String closetName) async {
Map body = {
"abc": userID,
"abc": closetName,
};
final response = await http.post(
Uri.http("abcd.com".toString(), '/link'),
body: body,
headers: {
"Accept": "application/json",
'Content-Type': "application/x-www-form-urlencoded"
},
);
final decodeData = utf8.decode(response.bodyBytes);
var jsonArray = jsonDecode(decodeData) as List;
List<ProductModel> products =
await jsonArray.map((e) => ProductModel.fromJSON(e)).toList();
print(products[0].title);
return products;
}
@override
void initState() {
productList(widget.userID, widget.closetName).then((value) {
generateProductList(value);
return;
});
super.initState();
}
Widget todayProductCard(String url, String name, String price, String mall,
String discount, String imageURL, String like) {
bool _isSelected = false;
if (name.length >= 15) {
name = name.substring(0, 15) + "...";
}
return GestureDetector(
onTap: () {
setState(() {
_isSelected = !_isSelected;
print(_isSelected.toString() + " " + name);
});
},
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Stack(
children: [
Image.network(
imageURL,
width: MediaQuery.of(context).size.width / 2.2,
height: MediaQuery.of(context).size.height / 4.5,
fit: BoxFit.cover,
),
Visibility(
visible: _isSelected,
child: Opacity(
opacity: 0.4,
child: Container(
decoration: BoxDecoration(
color: Colors.lightGreen,
border: Border.all(
color: Colors.green[900],
width: 3,
),
borderRadius: BorderRadius.circular(10),
),
width: MediaQuery.of(context).size.width / 2.2,
height: MediaQuery.of(context).size.height / 4.5,
),
),
),
],
),
),
Container(
width: MediaQuery.of(context).size.width / 2.2,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 70,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: MediaQuery.of(context).size.height / 200,
),
Text(
// "$mall",
_isSelected.toString(),
style: TextStyle(
fontWeight: FontWeight.w700,
color: Colors.grey[700],
fontSize: MediaQuery.of(context).size.width / 38,
),
),
Text(
"$name",
style: TextStyle(
color: Colors.grey[700],
fontSize: MediaQuery.of(context).size.width / 35,
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 200,
),
Row(
children: [
Text(
(discount == "") ? "" : "$discount ",
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.red,
fontSize:
MediaQuery.of(context).size.width / 30,
),
),
Text(
"$price",
style: TextStyle(
fontWeight: FontWeight.w900,
fontSize:
MediaQuery.of(context).size.width / 30,
),
),
],
),
],
),
),
],
),
),
),
],
),
);
}
generateProductList(List<ProductModel> productList) {
setState(() {
_productWidgetList.addAll(
List.generate(
productList.length,
(index) {
return todayProductCard(
productList[index].url,
productList[index].title,
productList[index].price,
productList[index].mallName,
productList[index].discount,
productList[index].image,
productList[index].likeBool,
);
},
),
);
});
}
bool toggle = false;
@override
Widget build(BuildContext context) {
print("qkwueiuqoieuqoieuoiqueoique");
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 30,
),
child: Icon(Icons.more_horiz),
)
],
// title: Text(widget.closetName),
title: Text(toggle.toString()),
centerTitle: true,
brightness: Brightness.light,
),
body: FutureBuilder(
future: productList(widget.userID, widget.closetName),
builder: (BuildContext context,
AsyncSnapshot<List<ProductModel>> snapshot) {
if (snapshot.hasData) {
return GridView.builder(
padding: EdgeInsets.fromLTRB(
12,
0,
12,
0,
),
shrinkWrap: true,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.7,
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
return _productWidgetList[index];
},
);
} else {
return Container();
}
}),
);
}
}