Flutter change state on all list item - flutter

Hey I am a newbie in flutter, I am trying to build an interview radio app
The issue I am facing is when changing state on switching music from one station to another, the "playing" and icon still don't change for the previously clicked object, but the new station starts playing
Here the station has switched but playing text has not yet gone, as well as the icon changed
Ideally, I want when switched, the playing and icon change should be switched to the one playing now, and one that's switched from should have icon showing as the rest
My code
class ItemWidget extends StatefulWidget {
final Item item;
ItemWidget({Key? key, required this.item}) : super(key: key);
#override
State<ItemWidget> createState() => _ItemWidgetState();
}
class _ItemWidgetState extends State<ItemWidget> {
static AudioPlayer player = AudioPlayer();
static String name = "";
static bool isPlaying = false;
static String error = '';
initRadioPlayer(namepassed, url) async {
try {
if (name == namepassed) {
player.stop();
name = "";
isPlaying = false;
setState(() {});
} else if (name != namepassed) {
if (isPlaying == true) {
await player.stop();
}
await player.setUrl(url);
player.play();
name = namepassed;
isPlaying = true;
setState(() {});
}
} catch (err) {
error = err.toString();
setState(() {});
}
}
#override
Widget build(BuildContext context) {
return Card(
child: ListTile(
onTap: () {
initRadioPlayer(widget.item.name, widget.item.url);
},
title: Text(widget.item.name),
subtitle: name == widget.item.name
? isPlaying
? Text('Playing')
: Text('')
: Text(''),
trailing: Icon(isPlaying
? name == widget.item.name
? CupertinoIcons.stop_circle
: CupertinoIcons.play_circle
: CupertinoIcons.play_circle),
textColor: Color.fromARGB(255, 31, 22, 22),
),
);
}
}

I used a callback function and kept the state of which one is playing in the parent just like Ivo Becker suggested:
void _update(String name, bool isPlaying) {
setState(() {
_name = name;
_isPlaying = isPlaying;
});
}
This goes in the parent and then is passed on to and called from the child:
class ItemWidget extends StatefulWidget {
final Item item;
final String name;
final bool isPlaying;
Function callback;
and on tap you call it:
widget.callback(station_name, true);

Related

when i click the floating action button this error pops up on the red screen what i want is it need to show up camera and recogonize text

'import 'package:flutter/material.dart';
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'camera.dart';
import 'package:tooler_noturk/functions/text_painter.dart';
class TextRecognizerView extends StatefulWidget {
#override
State<TextRecognizerView> createState() => _TextRecognizerViewState();
}
class _TextRecognizerViewState extends State<TextRecognizerView> {
final TextRecognizer _textRecognizer =
TextRecognizer(script: TextRecognitionScript.chinese);
bool _canProcess = true;
bool _isBusy = false;
CustomPaint? _customPaint;
String? _text;
#override
void dispose() async {
_canProcess = false;
_textRecognizer.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return CameraView(
title: 'Text Detector',
customPaint: _customPaint,
text: _text,
onImage: (inputImage) {
processImage(inputImage);
},
);
}
Future<void> processImage(InputImage inputImage) async {
if (!_canProcess) return;
if (_isBusy) return;
_isBusy = true;
setState(() {
_text = '';
});
final recognizedText = await _textRecognizer.processImage(inputImage);
if (recognizedText != null) {
final painter = TextRecognizerPainter(
recognizedText,
inputImage.inputImageData!.size,
inputImage.inputImageData!.imageRotation);
_customPaint = CustomPaint(painter: painter);
} else {
_customPaint = null;
}
_isBusy = false;
if (mounted) {
setState(() {});
}
}
}
CircleAvatar(
radius: 25,
child: FloatingActionButton(`your text`
onPressed: (() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =\>
TextRecognizerView()),
);
}),
child: const Icon(Icons.scanner),
),)'
The method 'any' was called on null.
Receiver: null
Tried calling: any(Closure: (dynamic) => bool)
The relevant error-causing widget was
TextRecognizerView`
when i click the floating action button it shows this error so what i want is when i click the floating action button it need to open camera and recogonize text using google mlkit text recogonition

flutter music current index not updating

List<SongModel> songs = item.data!;
return ListTile(
onTap: () {
audioPlayer.setAudioSource(
createPlayList(songs),
initialIndex: index,
);
audioPlayer.play();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PlayerView(
audioPlayer: audioPlayer,
songsList: songs,
initialIndex: index,
),
),
);
ConcatenatingAudioSource createPlayList(List<SongModel> songs) {
List<AudioSource> sources = [];
for (var song in songs) {
sources.add(AudioSource.uri(Uri.parse(song.uri!)));
}
return ConcatenatingAudioSource(children: sources);
}
I am using this method to get all the songs from audio query and it's working fine if i want to play a single song on the player view which is :
class PlayerView extends StatefulWidget {
PlayerView({
Key? key,
required this.audioPlayer,
required this.songsList,
required this.initialIndex,
}) : super(key: key);
AudioPlayer audioPlayer;
List<SongModel> songsList;
int initialIndex;
#override
State<PlayerView> createState() => _PlayerViewState();
}
class _PlayerViewState extends State<PlayerView> {
bool isPlaying = false;
String currentSongTitle = '';
int currentIndex = 0;
Stream<DurationState> get durationState =>
Rx.combineLatest2<Duration, Duration?, DurationState>(
widget.audioPlayer.positionStream,
widget.audioPlayer.durationStream,
(position, duration) =>
DurationState(position: position, total: duration ?? Duration.zero),
);
#override
void initState() {
super.initState();
widget.audioPlayer.currentIndexStream.listen((index) {
if (index != null) {
_updateCurrentPlayingSongDetails(index);
}
});
}
#override
void dispose() {
super.dispose();
}
i am updating title and artquery in this way
widget.songsList[widget.initialIndex].title,
QueryArtworkWidget(
id: widget.songsList[widget.initialIndex].id,
and this method for skipping to next or previous song which is working fine means it's skipping to next or previous but only one like if i am playing song 1 and i skip to next means song2 and then try to skip again it will keep playing song 2 which as far as i think is due to not updating the song list and i tried to do it but it's not working as it's supposed to be.
void _updateCurrentPlayingSongDetails(int index) {
setState(() {
if (widget.songsList.isNotEmpty) {
currentSongTitle = widget.songsList[index].title;
currentIndex = index;
}
});
}
So the conclusion of the problem is :
Main page view which is the first one is sending single index to other screen due to which only first played song can be skipped and it's also not updating the current state.
Hope i will find a solution from any of you and i will be waiting cuz i am trying to fix it from days but i am new in flutter so you can expect this.
You can use currentIndexStream, eg:
final AudioPlayer player = GetIt.I.get<AudioPlayer>();
player.currentIndexStream.listen((index) {
if (index != null) {
// your code
}
});

how to save controller.index value into a static variable?

class SignUpConvert extends StatefulWidget {
const SignUpConvert({ Key? key}) : super(key: key);
#override
_SignUpConvertState createState() => _SignUpConvertState();
}
class _SignUpConvertState extends State<SignUpConvert>
with SingleTickerProviderStateMixin {
TabController? tabController;
#override
void initState() {
super.initState();
tabController = TabController(vsync: this, length: 2);
print(tabController!.index);
}
#override
void dispose() {
super.dispose();
}
I want to reflect the current index in a static variable
class MyVariable{
static int indexCount = 0;
}
so that i can use it to navigate from a same button to different pages
the button is;
onSubmit: (_) {
if (MyVariable.indexCount == 0) {
Navigator.of(context).push(MaterialPageRoute(
builder: (builder) => LogInConvert()));
}
else if (MyVariable.indexCount == 1) {
Navigator.of(context).push(MaterialPageRoute(
builder: (builder) => SignUpConvert()));
}
},
but the controller.index is not saving in MyVariable.indexCount and i'm getting the default value i.e 0.
i am saving index using custom button
CustomButton(
index: widget.tabIndex,
route: widget.pageToNavigate,
backgroundColor: Color(0xff416bbd),
borderColor: Color(0xff416bbd),
name: 'Sign Up',
textColor: Colors.white,
),
the index value is then assigned to MyVariable.indexCount.
but it is not working!!
Use getx Storage to store the static value and read the value and getstorage.read("store");
dependencies:
get_storage: ^2.0.3
example:
static final _otherBox = () => GetStorage('MyPref');
final username = ''.val('username');
final age = 0.val('age');
final price = 1000.val('price', getBox: _otherBox);
// or
final username2 = ReadWriteValue('username', '');
final age2 = ReadWriteValue('age', 0);
final price2 = ReadWriteValue('price', '', _otherBox);

Can not call list from function

There is no problem calling class and make list. My problem is I can not reach that list in statefull widget. I miss something...
I call API for data and get "data". It's simply live-search with php.
You can see my try in code where I wrote
Text(tagObjs), //////////THİS PART CANNOT CALL LIST
class Body extends StatefulWidget {
#override
_BodyState createState() => _BodyState();
}
class _BodyState extends State<Body> {
bool searching = false;
String term;
bool error;
void getSuggestion() async {
var jsonResponse;
String url = "API";
//get suggestion function
var res = await http.post(url + "?term=" + Uri.encodeComponent(term));
if (res.statusCode == 200) {
setState(() {
jsonResponse = json.decode(res.body);
var tagObjsJson = jsonResponse['data'] as List;////////////MAKE LIST PART
List<Tag> tagObjs =
tagObjsJson.map((tagJson) => Tag.fromJson(tagJson)).toList();
print(tagObjs[0]); ////WORK FINE
});
} else {
//there is error
setState(() {
error = true;
});
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
.............
children: [
TextFormField(
..........
onChanged: (value) {
term = value; //update the value of query
getSuggestion(); //start to get suggestion
},
),
Text(tagObjs), //////////THİS PART CANNOT CALL LIST
],
),
),
),
));
}
}
//search suggestion data model to serialize JSON data
class Tag {
...........
}
My goal is basicly do foreach in php. With Listview.Builder I am gonna create Rows...
Declare List<Tag> tagObjs as a class property like searching, term, and error.
List<Tag> tagObjs = [];
bool searching = false;
String term;
bool error;
and remove List<Tag> from inside getSuggestion
tagObjs = tagObjsJson.map((tagJson) => Tag.fromJson(tagJson)).toList();

How to play multiple audio files simultaniously in flutter

I have been trying to run the multiple audio files at the same time each having a separate mute button. I have tried AudioPlayer Flutter plugin.
I have tried the following code but it makes the files run one by one, not simultaniously.
Please help!!
Future play() async {
await audioPlayer.play(url);
await audioPlayer2.play(url2);
setState(() {
playerState = AudioPlayerState.PLAYING;
});
}
May be their are more appropriate solutions but this solved my problem at the moment, I have used the plugin audioplayers and created multiple instances for each audio file.
Updated: For example for two audio files it's done like below:
enum PlayerState { stopped, playing, paused }
enum PlayerState1 { stopped1, playing1, paused1 }
class AudioScreen extends StatefulWidget {
#override
_AudioScreenState createState() =>_AudioScreenState();
}
class _AudioScreenState extends State<AudioScreen> {
//for first audio
AudioPlayer audioPlayer;
PlayerState playerState = PlayerState.stopped;
get isPlaying => playerState == PlayerState.playing;
//for second audio
AudioPlayer audioPlayer1;
PlayerState1 playerState1 = PlayerState1.stopped1;
get isPlaying1 => playerState1 == PlayerState1.playing1;
#override
void initState() {
super.initState();
audioPlayer = new AudioPlayer();
audioPlayer1 = new AudioPlayer();
}
Future play() async {
await audioPlayer.play(url);
setState(() {
playerState = PlayerState.playing;
});
await audioPlayer1.play(url1);
setState(() {
playerState1 = PlayerState1.playing1;
});
}
Future stop() async {
await audioPlayer.stop();
setState(() {
playerState = PlayerState.stopped;
});
await audioPlayer1.stop();
setState(() {
playerState1 = PlayerState1.stopped1;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Column(
children:[
IconButton(
onPressed:() play(),
iconSize: 70.0,
icon:Icon(Icons.play_circle_outline, size: 55),
),
IconButton(
onPressed: stop(),
iconSize: 55.0,
icon: Icon(Icons.stop),
),
]
),
);
}
}
This way you can multiple instances or just use a loop to create multiple instances for each audio.