我有一个列表视图,其中包含从对象列表(优惠(创建的元素。每个报价都有关于它自己的详细信息。我想在点击该图标后更改图标(_isFavIcon
(。但是当我点击它时,它会更改列表的每个元素(每个图标(。 同样在更改图标后,我想将它们添加到另一个列表中。但那是后来的事了。
下面是它的外观:列表视图
也许我应该使用ListView
而不是ListView.builder
?
这是我的代码:
class OfferList extends StatefulWidget {
final List<Offer> offers;
OfferList(this.offers);
@override
_OfferListState createState() => _OfferListState();
}
class _OfferListState extends State<OfferList> {
bool isPressed = true;
Icon _isFavIcon = new Icon(
Icons.favorite_border,
color: Colors.red,
);
@override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
_addToFavorites() {
_isFavIcon = new Icon(Icons.favorite, color: Colors.red);
}
return Container(
height: 700,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Colors.white,
Colors.lightBlueAccent.withOpacity(0.2)
])),
width: mediaQuery.size.width,
child: Card(
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
vertical: 15,
horizontal: 15,
),
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 1.2,
blurRadius: 7,
),
],
),
child: Image.asset(widget.offers[index].flag),
),
padding: EdgeInsets.all(5),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 150,
child: Text(
widget.offers[index].title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(
'From: ' +
DateFormat.yMMMd()
.format(widget.offers[index].dateFrom),
style: TextStyle(
color: Colors.grey,
),
),
Text(
'To: ' +
DateFormat.yMMMd()
.format(widget.offers[index].dateTo),
style: TextStyle(
color: Colors.grey,
),
),
],
),
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
RaisedButton(
color: Colors.lightBlueAccent,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
child: Text('Open'),
onPressed: () {},
),
Container(
padding: EdgeInsets.only(left: 10),
child: InkWell(
onTap: () {
setState(() {
_addToFavorites();
});
},
child: _isFavIcon,
),
),
],
),
),
],
),
),
),
],
);
},
itemCount: widget.offers.length,
),
);
}
}
您可以同时满足这两个要求(切换 favIcon 并拥有收藏夹列表(,添加列表并检查项目何时在该列表中以显示图标。
class OfferList extends StatefulWidget {
final List<Offer> offers;
OfferList(this.offers);
@override
_OfferListState createState() => _OfferListState();
}
class _OfferListState extends State<OfferList> {
bool isPressed = true;
List<Offer> _favOffers = [];
@override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
void _toggleFavorite(Offer offer) {
if (_favOffers.contains(offer)) {
_favOffers.remove(offer);
} else {
_favOffers.add(offer);
}
}
return Container(
height: 700,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Colors.white,
Colors.lightBlueAccent.withOpacity(0.2)
])),
width: mediaQuery.size.width,
child: Card(
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
vertical: 15,
horizontal: 15,
),
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 1.2,
blurRadius: 7,
),
],
),
child: Image.asset(widget.offers[index].flag),
),
padding: EdgeInsets.all(5),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 150,
child: Text(
widget.offers[index].title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(
'From: ' +
DateFormat.yMMMd()
.format(widget.offers[index].dateFrom),
style: TextStyle(
color: Colors.grey,
),
),
Text(
'To: ' +
DateFormat.yMMMd()
.format(widget.offers[index].dateTo),
style: TextStyle(
color: Colors.grey,
),
),
],
),
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
RaisedButton(
color: Colors.lightBlueAccent,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
child: Text('Open'),
onPressed: () {},
),
Container(
padding: EdgeInsets.only(left: 10),
child: InkWell(
onTap: () {
setState(() {
_toggleFavorite(widget.offers[index]);
});
},
child:
(_favOffers.contains(widget.offers[index]))
? Icon(
Icons.favorite,
color: Colors.red,
)
: Icon(
Icons.favorite_border,
color: Colors.black,
),
),
),
],
),
),
],
),
),
),
],
);
},
itemCount: widget.offers.length,
),
);
}
}
您实际上是覆盖了所有项目的_isFavIcon
。
您需要向Offer
模型添加一个名为isFavorite
的属性,并在 onTap 方法上切换isFavorite
属性
这是您的案例的完整工作示例
产品/服务模型
class Offer {
// other attributes
bool isFavorite = false;
}
报价清单小部件
class OfferList extends StatefulWidget {
final List<Offer> offers;
OfferList(this.offers);
@override
_OfferListState createState() => _OfferListState();
}
class _OfferListState extends State<OfferList> {
bool isPressed = true;
Icon _isNotFavIcon = new Icon(
Icons.favorite_border,
color: Colors.red,
);
Icon _isFavIcon = new Icon(
Icons.favorite,
color: Colors.red,
);
List<Offer> _offers;
@override
void initState() {
_offers = widget.offers;
super.initState();
}
@override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
return Container(
height: 700,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Colors.white,
Colors.lightBlueAccent.withOpacity(0.2)
])),
width: mediaQuery.size.width,
child: Card(
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
vertical: 15,
horizontal: 15,
),
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 1.2,
blurRadius: 7,
),
],
),
child: Image.asset(_offers[index].flag),
),
padding: EdgeInsets.all(5),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 150,
child: Text(
_offers[index].title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(
'From: ' +
DateFormat.yMMMd()
.format(_offers[index].dateFrom),
style: TextStyle(
color: Colors.grey,
),
),
Text(
'To: ' +
DateFormat.yMMMd()
.format(_offers[index].dateTo),
style: TextStyle(
color: Colors.grey,
),
),
],
),
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
RaisedButton(
color: Colors.lightBlueAccent,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
child: Text('Open'),
onPressed: () {},
),
Container(
padding: EdgeInsets.only(left: 10),
child: InkWell(
onTap: () {
setState(() {
_offers[index].isFavorite =
!_offers[index].isFavorite;
});
},
child: _offers[index].isFavorite
? _isFavIcon
: _isNotFavIcon,
),
),
],
),
),
],
),
),
),
],
);
},
itemCount: _offers.length,
),
);
}
}