我正在尝试使用Flutter开发音乐应用。轻按项目/音乐卡时,图标变为暂停图标以显示其正在播放。但是,当我点击card-1时,图标会更改(应更改),但是当我点击card-2或任何其他卡时,该卡也会更改图标,但card-1仍具有暂停图标。轻按任何其他卡时,如何将卡1的图标更改为默认图标?
当前,我正在使用ListView.builder()列出所有音乐卡。实际的卡是使用另一个文件中的有状态小部件构建的。状态管理在该文件中完成。
main.dart中的ListView
ListView.builder(
shrinkWrap: true,
controller: ScrollController(),
itemCount: allPodcasts.length,
itemBuilder: (BuildContext context, index){
return LongCard(podcast: allPodcasts[index]);
},
)
longcard.dart
class LongCard extends StatefulWidget {
final Podcast podcast;
LongCard({this.podcast});
@override
_LongCardState createState() => _LongCardState();
}
class _LongCardState extends State<LongCard> {
bool playingState;
@override
void initState() {
super.initState();
setState((){
playingState = false;
});
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(bottom: 15.0),
child: InkWell(
onTap: (){
setState((){
if(playingState){
playingState = false;
}else{
playingState = true;
}
});
},
child: Card(
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 1.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(topLeft: Radius.circular(10.0), bottomLeft: Radius.circular(10.0) ),
child: Image(
image: AssetImage(widget.podcast.image),
height: 100.0,
width: 100.0,
fit: BoxFit.fill
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
child: Align(
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
widget.podcast.date,
style: Theme.of(context).textTheme.body1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height:5.0),
Text(
widget.podcast.title,
style: Theme.of(context).textTheme.display1,
overflow: TextOverflow.ellipsis,
),
],
),
)
),
Expanded(
child: SizedBox()
),
Container(
alignment: Alignment.centerRight,
height: 100.0,
width: 70.0,
decoration: BoxDecoration(
color: lightCoral,
borderRadius: BorderRadius.only(topRight: Radius.circular(10.0), bottomRight: Radius.circular(10.0) ),
),
child: Center(
child: Icon(
(playingState == true ) ? Icons.pause : Icons.headset,
size: 40.0
)
)
),
],
)
),
),
);
}
我希望在点击一张卡时,将另一张卡上的图标更改为默认图标,然后将已轻按的卡上的图标更改为指示其活动状态。
答案 0 :(得分:0)
您不能像这样动态更改图标,因为它已经在Icon()小部件中定义了。如文档中所述,Icon()小部件不是交互式的。
https://api.flutter.dev/flutter/widgets/Icon-class.html
您应该将Icon()更改为IconButton(),然后可以使用类似于以下内容的iconData动态更改内部图标:
How to change IconButton's icon from callback function in flutter
或者您应该返回两个不同的Icon()类型,具体取决于布尔状态的值
child: Center(
child: playingState ? Icon(Icons.pause, size: 40.0) : Icon(Icons.headset, size: 40.0)
)
答案 1 :(得分:0)
通过包含ListView的父窗口小部件管理列表的状态。
您的 LongCard 小部件应该是仅显示数据而不管理数据的无状态小部件。它只会告诉父窗口小部件在按下时切换到另一个索引。
class Page extends StatefulWidget {
@override
_PageState createState() => _PageState();
}
class _PageState extends State<Page> {
// List index of the podcast that is playing right now
int activeIndex;
void _setActivePodcast(int index) {
setState(() {
activeIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Container(
child: ListView.builder(
shrinkWrap: true,
controller: ScrollController(),
itemCount: allPodcasts.length,
itemBuilder: (BuildContext context, index) {
return LongCard(
podcast: allPodcasts[index],
listIndex: index,
isPlaying: activeIndex == index,
onPress: _setActivePodcast,
);
},
),
);
}
}
class LongCard extends StatelessWidget {
final Podcast podcast;
final bool isPlaying;
final int listIndex;
final Function(int index) onPress;
const LongCard({
Key key,
this.podcast,
this.listIndex,
this.onPress,
this.isPlaying: false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(bottom: 15.0),
child: InkWell(
onTap: () => onPress(listIndex),
child: Card(
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 1.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0)),
child: Image(
image: AssetImage(podcast.image),
height: 100.0,
width: 100.0,
fit: BoxFit.fill),
),
Padding(
padding:
EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
child: Align(
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
podcast.date,
style: Theme.of(context).textTheme.body1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 5.0),
Text(
podcast.title,
style: Theme.of(context).textTheme.display1,
overflow: TextOverflow.ellipsis,
),
],
),
)),
Expanded(child: SizedBox()),
Container(
alignment: Alignment.centerRight,
height: 100.0,
width: 70.0,
decoration: BoxDecoration(
color: lightCoral,
borderRadius: BorderRadius.only(
topRight: Radius.circular(10.0),
bottomRight: Radius.circular(10.0)),
),
child: Center(
child: Icon(
isPlaying ? Icons.pause : Icons.headset,
size: 40.0,
),
),
),
],
)),
),
);
}
}