简体   繁体   English

如何基于另一个窗口小部件中的动作更新UI或更改窗口小部件中的状态?

[英]How to update UI or change state in a widget based on an action in another widget?

I'm trying my hands on a music app using flutter. 我正在尝试使用颤动的音乐应用程序。 When an item/music card is tapped, the icon changes to the pause icon to show that its playing. 轻按项目/音乐卡时,图标变为暂停图标以显示其正在播放。 But when i tap card-1, the icon changes(as it should), but when i tap card-2 or any other card, that card also changes icon but card-1 still has the pause icon. 但是,当我点击card-1时,图标会更改(应更改),但是当我点击card-2或任何其他卡时,该卡也会更改图标,但card-1仍具有暂停图标。 How do i change the icon of card-1 to default icon when any other card is tapped? 轻按任何其他卡时,如何将卡1的图标更改为默认图标?

Currently im using a ListView.builder() to list out all the music cards. 目前,我正在使用ListView.builder()列出所有音乐卡。 the actual card is built with a stateful widget in another file. 实际的卡是使用另一个文件中的有状态小部件构建的。 and the state management is done in that file. 状态管理在该文件中完成。

ListView in main.dart main.dart中的ListView

ListView.builder(
  shrinkWrap: true,
  controller: ScrollController(),
  itemCount: allPodcasts.length,
  itemBuilder: (BuildContext context, index){
    return LongCard(podcast: allPodcasts[index]);
  },
)

longcard.dart 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
                  )
                )
              ),
            ],
          )
        ),
      ),
    );
}

I expect that on tap on one card the icons in the other cards are changed to the default icon and then the icon on the tapped card is changed to indicate that its active. 我希望在点击一张卡时,将另一张卡中的图标更改为默认图标,然后将已轻按的卡上的图标更改为指示其处于活动状态。

You can't dynamically change the icon like that because as it is already defined in the Icon() widget. 您不能像这样动态更改图标,因为它已经在Icon()小部件中定义了。 The Icon() widget is not interactive as explained in the documentation. Icon()小部件不是交互式的,如文档中所述。

https://api.flutter.dev/flutter/widgets/Icon-class.html https://api.flutter.dev/flutter/widgets/Icon-class.html

You should change Icon() to IconButton() and then you can change the icon inside dynamically using iconData similar to this: 您应该将Icon()更改为IconButton(),然后可以使用类似于以下内容的iconData动态更改图标:

How to change IconButton's icon from callback function in flutter 如何在Flutter中从回调函数更改IconButton的图标

Or you should return two different Icon() types depending on the value of the boolean playingState 或者,您应该根据布尔型playState的值返回两种不同的Icon()类型

 child: Center(
    child: playingState ? Icon(Icons.pause, size: 40.0) : Icon(Icons.headset, size: 40.0)
 )

Manage the state of the list from the parent widget that contains the ListView. 通过包含ListView的父窗口小部件管理列表的状态。

Your LongCard widget should be a stateless widget that only displays the data, not manages it. 您的LongCard小部件应该是仅显示数据而不管理数据的无状态小部件。 It will only tell the parent widget to switch to another index on press. 它只会告诉父窗口小部件在印刷时切换到另一个索引。

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,
                    ),
                  ),
                ),
              ],
            )),
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM