简体   繁体   中英

How to make Listview of unique buttons in Flutter?

I'm developing an app that creates a list of audio recordings. For every recording I want the app to generate different interface for recording and playing the audio, some sort of form that keeps the name and unique id of the recording. It looks like this

Unfortunately when i press the play button on one of those recordings, every single play button for all recordings toggles from Icons.play to Icons.stop. I only want the desired button to change icon, I tried using Keys and GlobalKeys but with no success.

code for audioForm looks like this

  _audioForm(double screenWidth, double screenHeight, recordi) => Padding(
        padding: const EdgeInsets.only(top: 12.0),
        child: Row(
          children: [
            SizedBox(
              height: screenHeight / 9,
              width: screenWidth * (2 / 10),
              child: TextField(
                style: TextStyle(
                  fontSize: 24.0,
                ),
                decoration: InputDecoration(
                    border: OutlineInputBorder(), hintText: 'Key'),
              ),
            ),
            SizedBox(
              height: screenHeight / 9,
              width: screenWidth * (5 / 10),
              child: TextField(
                style: TextStyle(fontSize: 24.0),
                decoration: InputDecoration(
                    border: OutlineInputBorder(), hintText: 'Name'),
              ),
            ),
            SizedBox(
              width: screenWidth * 1.5 / 10,
              child: Center(
                child: InkWell(
                  key: Key("record"),
                  child: Icon(
                    Icons.circle,
                    color: Colors.red,
                  ),
                  onTap: () {
                    _scaffoldKey.currentState.showBottomSheet(
                        (BuildContext context) => _recordBottomSheet(
                            screenWidth, screenHeight, recordingList[recordi]));
                  },
                ),
              ),
            ),
            SizedBox(
              width: screenWidth * 1.5 / 10,
              child: Center(
                child: InkWell(
                  child: _isPlaying
                      ? Icon(
                          Icons.stop,
                          size: 35,
                        )
                      : Icon(
                          Icons.play_arrow,
                          size: 35,
                        ),
                  onTap: () {
                    if (_isPlaying == true)
                      _isPlaying = false;
                    else
                      _isPlaying = true;
                    setState(() {
                    });
                    // }
                  },
                ),
              ),
            )
          ],
        ),
      );

I excluded code regarding sound operations, since it's unimportant for this case, I only left the bool that toggles button. I would really appreciate some advice on how to make every button unique to a recording.

And this is Listview, in which audio forms are stored

child: ListView.builder(
              itemCount: recordingList.length + 1,
              itemBuilder: (context, index) {
                if (index < recordingList.length) {
                  return _audioForm(screenWidth, screenHeight, index);
                } else {
                  return _addButton();
                }
              }),

All buttons in your code are using the same bool variable... So if you call setState() the entire widget-tree will be rebuild an all buttons will update their appearence to the changed bool value. Try to create a new StatefulWidget where every button will have its own specific bool value.

Or use a map with bool values, like this

Map<int,bool> isPlaying = {
//example values
0: true,
1: false,
};

your onTap-method should then look like this:

onTap: () {
    isPlaying.update(index, (value) => !value, ifAbsent: ()=> true);
   setState(() {});
    },

your icon widget should look like this:

child: 
      Icon(
        (_isPlaying[index] ?? false) ? Icons.stop : Icons.play_arrow,
        size: 35,
       ),
                 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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