我正在使用flutter show search()和SearchDelegate扩展的类。 我将类对象的列表传递给委托类。在buildResult()方法中,我需要创建一个自定义列表视图。每个列表视图属性都需要更改其基础窗口小部件。但是我不能在buildResults()函数中使用setstate(),因为它没有生成器。 这是我的代码。希望一切都有意义。仅供参考,它是对在线商店产品的简单搜索。
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:rashan/models/order.dart';
import 'package:rashan/models/product.dart';
class ProductScreen extends StatefulWidget {
static final String id = "product_screen";
final String category;
final String subCategory;
ProductScreen({
@required this.category,
@required this.subCategory,
});
@override
_ProductScreenState createState() => _ProductScreenState();
}
class _ProductScreenState extends State<ProductScreen> {
final productList = <Product>[];
@override
void initState() {
super.initState();
FirebaseDatabase.instance
.reference()
.child("Data")
.child("All Products")
.child(widget.category)
.child(widget.subCategory)
.once()
.then((snapshot) {
setState(() {
var result = snapshot.value.values as Iterable;
for (var item in result) {
var product = Product(
id: item['id'],
name: item['name'],
image: item['image'],
price: item['price'],
quantity: item['quantity'],
category: item['category'],
subCategory: item['subCategory']);
productList.add(product);
}
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
centerTitle: true,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {
Navigator.pop(context);
},
),
title: Text(
"Rashan",
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 48.0,
fontFamily: "Billabong"),
),
actions: <Widget>[
productList.length != 0
? IconButton(
icon: Icon(
Icons.search,
color: Colors.black,
),
onPressed: () {
showSearch(
context: context, delegate: ProductSearch(productList));
},
)
: Container()
],
),
body: Center(
child: Container(
child: productList.length == 0
? Text(
"Loading Products ...!",
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 16.0,
fontWeight: FontWeight.w500),
)
: ListView.builder(
itemCount: productList.length,
itemBuilder: (BuildContext context, int index) {
return productUI(productList[index]);
},
)),
),
);
}
Widget productUI(Product product) {
String _price = product.price;
var order = new Order();
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: Colors.white,
elevation: 5.0,
margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Container(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Container(
height: 120.0,
width: 120.0,
child: Image.network(product.image),
),
SizedBox(
width: 10.0,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 5.0),
padding: EdgeInsetsDirectional.only(end: 4.0),
child: Text(
product.name,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.w600),
),
),
SizedBox(
height: 10.0,
),
Text(product.category),
Text(product.subCategory),
Text(
'Price: Rs $_price ',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 16.0,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 10.0,
),
Container(
margin:
EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
height: 40.0,
color: Theme.of(context).primaryColor,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
order.decrementQuantity(product.id);
});
},
child: Container(
height: 50.0,
width: 50.0,
child: Icon(
Icons.remove,
color: Colors.white,
),
),
),
Expanded(
child: Center(
child: Text(
order.getQuantity(product.id) == 0
? "Add to Cart"
: order.getQuantity(product.id).toString(),
style: TextStyle(color: Colors.white),
)),
),
GestureDetector(
onTap: () {
setState(() {
order.addOrIncrement(product.id);
});
},
child: Container(
height: 50.0,
width: 50.0,
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
)
],
),
)
],
),
),
);
}
}
class ProductSearch extends SearchDelegate<Product> {
List<Product> _productList;
ProductSearch(this._productList);
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(
Icons.clear,
),
onPressed: () {
query = '';
})
];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(
Icons.arrow_back,
),
onPressed: () {
close(context, null);
});
}
@override
Widget buildResults(BuildContext context) {
List<Product> searchResult = [];
for (var product in _productList) {
if (query.isNotEmpty && product.name.toLowerCase().contains(query)) {
searchResult.add(product);
print(product.name);
}
}
return Container(
child: ListView.builder(
itemCount: searchResult.length,
itemBuilder: (BuildContext context, int index) {
return productUI(context, searchResult[index]);
},
),
);
}
@override
Widget buildSuggestions(BuildContext context) {
return Container();
}
Widget productUI(BuildContext context, Product product) {
String _price = product.price;
var order = new Order();
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: Colors.white,
elevation: 5.0,
margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Container(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Container(
height: 120.0,
width: 120.0,
child: Image.network(product.image),
),
SizedBox(
width: 10.0,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 5.0),
padding: EdgeInsetsDirectional.only(end: 4.0),
child: Text(
product.name,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.w600),
),
),
SizedBox(
height: 10.0,
),
Text(product.category),
Text(product.subCategory),
Text(
'Price: Rs $_price ',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 16.0,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 10.0,
),
Container(
margin:
EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
height: 40.0,
color: Theme.of(context).primaryColor,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
// setState(() {
order.decrementQuantity(product.id);
// });
},
child: Container(
height: 50.0,
width: 50.0,
child: Icon(
Icons.remove,
color: Colors.white,
),
),
),
Expanded(
child: Center(
child: Text(
order.getQuantity(product.id) == 0
? "Add to Cart"
: order.getQuantity(product.id).toString(),
style: TextStyle(color: Colors.white),
)),
),
GestureDetector(
onTap: () {
// setState(() {
order.addOrIncrement(product.id);
// });
},
child: Container(
height: 50.0,
width: 50.0,
child: Icon(
Icons.add,
color: Colors.white,
),
),
)
],
),
)
],
),
)
],
),
),
);
}
}
答案 0 :(得分:0)
如果您希望每个列表项都有一个状态,则可以只创建一个StatefulWidget
而不是使用方法productUI()
。如果要从上方的小部件(列表)控制状态,则只需为该级别创建一个StatefulWidget
。
class ProductUi extends StatefulWidget {
final Product product;
ProductScreen(@required this.product) : assert(product != null);
@override
_ProductUiState createState() => _ProductUiState();
}
class _ProductUiState extends State<ProductUi> {
@override
Widget build(BuildContext context) => productUI(context, widget.product);
Widget productUI(BuildContext context, Product product) {
// ...
// now you can setState from taps and delegates
}
}