SOLUTION (see below for original post) :
I managed to get what I wanted with the help of ChatGPT.
You first need to create an AppState element. It can be string, integer, whatever you need to be returned after the user selected the radio element. In my case, it's the id of the sound.
Secondly, you need to create a custom widget :
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:just_audio/just_audio.dart';
class SoundsListView extends StatefulWidget {
const SoundsListView({super.key, this.width, this.height});
final double? width;
final double? height;
@override
State<SoundsListView> createState() => _SoundsListViewState();
}
class _SoundsListViewState extends State<SoundsListView> {
final AudioPlayer player = AudioPlayer();
List<dynamic> sounds = [];
int? _selectedIndex;
int?
soundID; // Init the local appstate variable
@override
void initState() {
super.initState();
print("initState: fetchSounds is being called.");
fetchSounds();
}
fetchSounds() async {
try {
final response = await Supabase.instance.client
.from('sounds')
.select()
.order('id', ascending: true)
.execute();
final data = response.data;
if (data != null) {
print("fetchSounds: Data fetched - $data");
setState(() {
sounds = data;
_selectedIndex = null;
soundID = null; // Reset the ID of the sound
print("fetchSounds: setState called.");
});
} else {
print("fetchSounds: No data collected.");
}
} catch (e) {
print("fetchSounds: Exception: - $e");
}
}
@override
void dispose() {
player.dispose();
super.dispose();
print("dispose: SoundListView was disposed.");
}
@override
Widget build(BuildContext context) {
print(
"build: Building SoundsListView with ${sounds.length} sounds.");
return Container(
width: widget.width,
height: widget.height,
child: ListView.builder(
itemCount: sounds.length,
itemBuilder: (context, index) {
var sound = sounds[index];
print("ListView.builder: Building the element: $index");
return RadioListTile(
title: Text(sound['name']),
value: index,
groupValue: _selectedIndex,
onChanged: (value) async {
setState(() {
_selectedIndex = value;
FFAppState().update(() {
FFAppState().soundID =
sound['id']; // Store the soundID selected
});
});
print("RadioListTile: Playing the following sound ${sound['name']}");
await player.setUrl(sound['sound_url']);
player.play();
},
);
},
),
);
}
}
The important part here is
int?
soundID; // Init the local appstate variable
that you need to change for your appstate variable type and name and
FFAppState().update(() {
FFAppState().soundID =
sound['id']; // Store the soundID selected
});
That you need to change as well.
Note that I'm using Supabase to collect the list of my sounds so you will need to modify this part to make it work
final response = await Supabase.instance.client
.from('sounds')
.select()
.order('id', ascending: true)
.execute();
final data = response.data;
if (data != null) {
print("fetchSounds: Data fetched - $data");
setState(() {
sounds = data;
_selectedIndex = null;
soundID = null; // Reset the ID of the sound
print("fetchSounds: setState called.");
});
} else {
print("fetchSounds: No data collected.");
}
} catch (e) {
print("fetchSounds: Exception: - $e");
}
}
Once you select the sound (or anything) you want from the radiobuttion, it will automatically update the appstate variable. You can then use this value to do any actions you want to.
Voilà ! Hope it can help!
ORIGINAL THREAD
Hi everyone,
As the title implies, I'm trying to display a list of sounds that users can choose from, with a little speaker icon next to each sound. If the user clicks on the speaker, it plays the correct sound. Since I want them to be able to select only one, I went with the radio button widget.
The issue is that I cannot get it to work. I cannot generate a list of radio buttons like I can do with a listview, where each radio button has its own state.