I am using audioplayers: ^0.18.0 for playing audio when the screen appears.
This is code for playing audio which is called in initstate:
void initState() {
startTimer();
playLocalAsset();
super.initState();
}
This is to call the play function:
AudioPlayer player;
Future<AudioPlayer> playLocalAsset() async {
AudioCache cache = new AudioCache();
//At the next line, DO NOT pass the entire reference such as assets/yes.mp3. This will not work.
//Just pass the file name only.
return await cache.play("audio.wav");
}
I want to stop it inside onPressed():
onPressed: () {
// this is where stop audio should be used
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return Homepage(
device: widget.device,
);
},
),
);
},
How can I stop the audio sound when I press the button of Cancel which I have made in my flutter app. I cannot call it as Future to stop it, kindly help me out.
Nabia Salman
I made an audio player 1 year ago. I did not really know what i was doing. I just tried to do something.
I copied my code here. I hope it could help you.
You can use this code freely. This code is made before Flutter 2.2, so it can be some error due to the null safety.
class _SongsPage extends State<SongsPage> {
List<String> pictures = <String>["assets/images/thespectre.jpg", "assets/images/home.jpg", "assets/images/alone.jpg", "assets/images/lostf.jpg", "assets/images/breakingme.png", "assets/images/cry.jpg", "assets/images/onelife.jpg", "assets/images/coming.jpg", "assets/images/allnight.jpg", "assets/images/wildest.jpg", "assets/images/lovers.jpg", "assets/images/nothing.jpg"];
List<String> songname = <String>["The Spectre", "Home", "Alone", "Don't Leave Me Now", "Breaking Me", "Cry", "One Life", "Coming Home", "All Night", "Wildest Dream", "Lovers For The Weekend", "Nothing Stopping Me"];
List<String> performer = <String>["Alan Walker", "Martin Garrix", "Marshmello", "Lost Frequencies", "Topic", "Gryffin", "Mike Perry", "Dimitri Vangelis & Wyman", "Afrojack", "Thomas Gold", "John De Sohn", "Vicetone"];
List<String> song = <String>['TheSpectre.mp3', 'Home.mp3', 'Alone.mp3', 'DontLeaveMeNow.mp3', 'BreakingMe.mp3', 'Cry.mp3', 'OneLife.mp3', 'ComingHome.mp3', 'AllNight.mp3', 'WildestDream.mp3', 'LoversForTheWeekend.mp3', 'NothingStoppingMe.mp3'];
bool isPlaying = false;
bool isLiked = false;
int index = 0;
Duration _duration = new Duration();
Duration _position = new Duration();
AudioPlayer advancedPlayer;
AudioCache audioCache;
_SongsPage(int indexer){
index = indexer;
}
#override
void initState() {
super.initState();
initPlayer();
}
void initPlayer() {
advancedPlayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: advancedPlayer);
advancedPlayer.durationHandler = (d) => setState(() {
_duration = d;
});
advancedPlayer.positionHandler = (p) => setState(() {
_position = p;
});
}
String localFilePath;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [kbackgroundcolorpink, kbackgroundcolorblue],
tileMode: TileMode.repeated,
),
),
child: Column(
children: <Widget>[
Expanded(
flex: 10,
child: Column(
children: <Widget>[
//Picture
Container(
margin: EdgeInsets.only(top: 120),
width: 200,
height: 200,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: kblack.withOpacity(0.4),
spreadRadius: 3,
blurRadius: 4,
offset: Offset(3, 2),
),
],
),
child: Image.asset(pictures[index]),
),
//Song and Performer
Container(
margin: EdgeInsets.only(top: 20),
height: 80,
child: Column(
children: <Widget>[
Text(songname[index], style: kheadlinesong),
Text(performer[index], style: kheadlineperformer),
],
),
),
//Timer
Container(
padding: EdgeInsets.only(right: 36),
child: Align(
alignment: Alignment.centerRight,
child: Text((_position.inMinutes).toString() + ":" + (_position.inSeconds - (_position.inMinutes * 60)).toString().padLeft(2, "0") + " / " + (_duration.inMinutes).toString() + ":" + (_duration.inSeconds - (_duration.inMinutes * 60)).toString().padLeft(2, "0"), textAlign: TextAlign.right, style: kheadlineperformer),
),
),
//Line
Container(
padding: EdgeInsets.only(right: 12, left: 12),
child: Slider(
activeColor: kbackgroundcolorpink,
inactiveColor: kbackgroundcolorblue,
value: _position.inSeconds.toDouble(),
min: 0.0,
max: _duration.inSeconds.toDouble(),
onChanged: (double value) {
setState(() {
seekToSecond(value.toInt());
value = value;
});
}),
),
],
),
),
Expanded(
flex: 3,
child: Container(
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(bottom: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Spacer(),
Spacer(),
IconButton(
icon: PreviousIcon,
onPressed: () {PreviousIconClick();},
),
Spacer(),
IconButton(
icon: Icon(isPlaying ? PauseIcon : PlayIcon2, color: kwhite, size: 40),
onPressed: () {PausePlayIconClick();},
),
Spacer(),
IconButton(
icon: NextIcon,
onPressed: () {NextIconClick();},
),
Spacer(),
Spacer(),
],
),
),
Container(
padding: EdgeInsets.only(top: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Spacer(),
IconButton(
icon: Icon(isLiked ? LikeIcon2 : LikeIcon, color: kwhite, size: 26),
onPressed: () {LikeIconClick();},
),
Spacer(),
IconButton(
icon: ShareIcon,
onPressed: () {ShareIconClick();},
),
Spacer(),
IconButton(
icon: Icon(ReplayIcon, color: isPlaying ? kbackgroundcolorpink : kwhite, size: 26),
onPressed: () {ReplayIconClick();},
),
Spacer(),
IconButton(
icon: AddToListIcon,
onPressed: () {AddIconClick();},
),
Spacer(),
],
),
),
],
),
),
),
],
),
),
);
}
void seekToSecond(int second) {
Duration newDuration = Duration(seconds: second);
advancedPlayer.seek(newDuration);
}
void PreviousIconClick(){
if(index == 0){
index = index;
Playing();
}
else {
index--;
Playing();
}
}
void NextIconClick(){
if (index == song.length - 1){
index = 0;
Playing();
}
else{
index++;
Playing();
}
}
void LikeIconClick(){
if(isLiked){
setState(() {
isLiked = false;
});
}
else{
setState(() {
isLiked = true;
});
}
}
void ReplayIconClick(){
}
void AddIconClick(){
}
void ShareIconClick(){
}
void Playing(){
audioCache.play(song[index]);
setState(() {
isPlaying = true;
});
}
void PausePlayIconClick(){
if(isPlaying){
advancedPlayer.pause();
setState(() {
isPlaying = false;
});
}
else{
audioCache.play(song[index]);
setState(() {
isPlaying = true;
});
}
}
}
And this is look like this, and works fine.
I have answered my own question
Initializing the function for play and stop
AudioPlayer player = new AudioPlayer();
AudioCache audioCache;
String mp3Uri = "audio.wav";
void _playSound() {
audioCache = new AudioCache(fixedPlayer: player);
audioCache.play("audio.wav");
}
void _stopSound() {
player.stop();
}
Now call _playSound function inside initState and inside onPressed call _stopSound function
Please try this flutter package audioplayers
assets:
- assets/icons/
- ringtone.mp3
- ringer.mp3
- miss_call.mp3
import 'dart:io';
import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
AudioPlayer advancedPlayer = AudioPlayer();
AudioCache audioCache = AudioCache();
class PlayAudioTone{
playRingTone() {
audioCache.getAbsoluteUrl('ringtone.mp3').then((value) {
print(value);
final file = new File(value);
advancedPlayer.play(file.path, isLocal: true,);
});
}
stopRingTone(){
advancedPlayer.stop();
}
playRinger() {
audioCache.getAbsoluteUrl('ringer.mp3').then((value) {
print(value);
final file = new File(value);
advancedPlayer.play(file.path, isLocal: true);
// advancedPlayer.setVolume(0.01);
});
}
stopRinger(){
advancedPlayer.stop();
}
}
Related
I am developing an audio player application using Flutter, I am using on_audio_query package to get audio files from device storage, and just_audio package for the audio player.
when I created the project, in the audio player I used setState to handle state management, and now, I want to convert to bloc pattern but when I tried to do that I faced a lot of issues and couldn't fix them.
I will attach the code of the audio player and also basic cubit code and if someone guided me or showed me how to convert I would appreciate it.
I'm sorry if the code is confusing but I don't know how to add it correctly.
audio player code
import 'package:just_audio/just_audio.dart';
import 'package:dorosi/shared/ui/my_icon.dart';
import 'package:dorosi/shared/ui/my_text.dart';
import 'package:flutter/material.dart';
import 'package:on_audio_query/on_audio_query.dart';
class AudioPlayerWithUrl extends StatefulWidget {
final SongModel songModel;
const AudioPlayerWithUrl({required this.songModel, Key? key})
: super(key: key);
#override
State<AudioPlayerWithUrl> createState() => _AudioPlayerWithUrlState();
}
class _AudioPlayerWithUrlState extends State<AudioPlayerWithUrl> {
final audioPlayer = AudioPlayer();
bool isPlaying = false;
Duration duration = const Duration();
Duration position = const Duration();
bool isPressed = false;
#override
void initState() {
super.initState();
setAudio();
playAudio();
}
Future setAudio() async {
audioPlayer.setLoopMode(LoopMode.off);
audioPlayer.setAudioSource(
AudioSource.uri(
Uri.parse(widget.songModel.uri!),
),
);
isPlaying = true;
audioPlayer.durationStream.listen((audioDuration) {
setState(() {
duration = audioDuration!;
});
});
audioPlayer.positionStream.listen((audioPosition) {
setState(() {
position = audioPosition;
});
});
}
#override
void dispose() {
audioPlayer.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const MyText(
writtenText: 'Now Playing',
textSize: 23,
textColor: Colors.black,
),
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: const MyIcon(
icon: Icons.arrow_back,
iconColor: Colors.black,
)),
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0,
actions: [
IconButton(
onPressed: () {},
icon: const MyIcon(
icon: Icons.more_vert,
iconColor: Colors.black,
),
),
const SizedBox(width: 10)
],
),
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 15),
const CircleAvatar(
backgroundColor: Color(0xFFc61104),
radius: 100,
child: MyIcon(
icon: Icons.music_note,
iconSize: 100,
iconColor: Colors.white,
),
),
const SizedBox(
height: 15,
),
const SizedBox(height: 15),
MyText(
writtenText: widget.songModel.title,
textSize: 24,
textWeight: FontWeight.bold,
),
const SizedBox(height: 4),
MyText(
writtenText: widget.songModel.album!,
textSize: 20,
),
const SizedBox(height: 10),
Slider(
activeColor: Colors.orange,
inactiveColor: Colors.black87,
min: 0,
max: duration.inSeconds.toDouble(),
value: position.inSeconds.toDouble(),
onChanged: (value) async {
isPlaying = true;
final position = Duration(seconds: value.toInt());
await audioPlayer.seek(position);
await audioPlayer.play();
}),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MyText(
writtenText: formatTime(position),
textWeight: FontWeight.bold),
TextButton(
style: TextButton.styleFrom(primary: Colors.black),
onPressed: () {
setState(() {
showRemainingTime();
isPressed = !isPressed;
});
},
child: isPressed
? showRemainingTime()
: MyText(
writtenText: ' ${formatTime(duration)}',
textWeight: FontWeight.bold,
),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
backgroundColor: const Color(0xFFc61104),
radius: 23,
child: IconButton(
onPressed: () async {
if (position >= const Duration(seconds: 10)) {
seekTo(position.inSeconds - 10);
} else {
setState(() {
seekTo(const Duration(seconds: 0).inSeconds);
isPlaying = false;
});
pauseAudio();
}
},
icon: const MyIcon(
icon: Icons.settings_backup_restore,
iconSize: 30,
iconColor: Colors.white,
)),
),
const SizedBox(width: 40),
CircleAvatar(
backgroundColor: const Color(0xFFc61104),
radius: 35,
child: IconButton(
icon: Icon(
isPlaying ? Icons.pause : Icons.play_arrow,
color: Colors.white,
),
iconSize: 50,
onPressed: () {
setState(() {
if (isPlaying) {
pauseAudio();
} else {
playAudio();
}
isPlaying = !isPlaying;
});
},
),
),
const SizedBox(width: 40),
CircleAvatar(
radius: 23,
backgroundColor: const Color(0xFFc61104),
child: IconButton(
onPressed: () async {
if (position < duration - const Duration(seconds: 10)) {
seekTo(position.inSeconds + 10);
} else {
setState(() {
seekTo(duration.inSeconds);
isPlaying = false;
});
pauseAudio();
}
},
icon: const MyIcon(
icon: Icons.forward_10,
iconSize: 30,
iconColor: Colors.white,
)),
),
],
),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(width: 40),
ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.orange),
onPressed: () {
setState(() {
if (audioPlayer.speed == 1) {
adjustAudioSpeed();
debugPrint('${audioPlayer.speed}');
} else if (audioPlayer.speed == 1.25) {
adjustAudioSpeed2();
} else if (audioPlayer.speed == 1.5) {
adjustAudioSpeed3();
} else if (audioPlayer.speed == 1.75) {
adjustAudioSpeed4();
} else if (audioPlayer.speed == 2) {
setAudioNormalSpeed();
}
});
},
child: MyText(
writtenText: '${audioPlayer.speed}',
textSize: 18,
textColor: Colors.black,
)),
const SizedBox(width: 40),
],
)
],
),
)),
);
}
Widget showRemainingTime() {
return MyText(
writtenText: '- ${formatTime(duration - position)}',
textWeight: FontWeight.bold,
);
}
seekTo(int seconds) {
audioPlayer.seek(Duration(seconds: seconds));
}
playAudio() {
audioPlayer.play();
}
pauseAudio() {
audioPlayer.pause();
}
setAudioNormalSpeed() {
audioPlayer.setSpeed(1);
}
adjustAudioSpeed() {
audioPlayer.setSpeed(1.25);
}
adjustAudioSpeed2() {
audioPlayer.setSpeed(1.5);
}
adjustAudioSpeed3() {
audioPlayer.setSpeed(1.75);
}
adjustAudioSpeed4() {
audioPlayer.setSpeed(2);
}
playNextAudio() {
audioPlayer.seekToNext();
}
playPreviousAudio() {
audioPlayer.seekToPrevious();
}
String formatTime(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, '0');
final hours = twoDigits(duration.inHours);
final minutes = twoDigits(duration.inMinutes.remainder(60));
final seconds = twoDigits(duration.inSeconds.remainder(60));
return [
if (duration.inHours > 0) hours,
minutes,
seconds,
].join(':');
}
}
player cubit code
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
part 'player_state.dart';
class PlayerCubit extends Cubit<PlayerState> {
static PlayerCubit get(context) => BlocProvider.of(context);
PlayerCubit() : super(PlayerInitialState());
}
player state code
part of 'player_cubit.dart';
#immutable
abstract class PlayerState {}
class PlayerInitialState extends PlayerState {}
class PlayerPlayingState extends PlayerState {}
class PlayerPauseState extends PlayerState {}
Firstly when i downloaded the plugin for Flutter Bluetooth serial few months ago, it was working fine.
But now, when i run the app it throws the following exceptions and errors.
1.When i choose the devices and try to connect them this error occurs
When i tap on the refresh button this error occurred
Here is the code for Bluetooth plugin.
import 'dart:async';
import 'dart:convert';
// For using PlatformException
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
class BluetoothApp extends StatefulWidget {
#override
_BluetoothAppState createState() => _BluetoothAppState();
}
class _BluetoothAppState extends State<BluetoothApp> {
// Initializing the Bluetooth connection state to be unknown
BluetoothState _bluetoothState = BluetoothState.UNKNOWN;
// Initializing a global key, as it would help us in showing a SnackBar later
final GlobalKey<ScaffoldMessengerState> _scaffoldKey = new GlobalKey<ScaffoldMessengerState>();
// Get the instance of the Bluetooth
FlutterBluetoothSerial _bluetooth = FlutterBluetoothSerial.instance;
// Track the Bluetooth connection with the remote device
BluetoothConnection connection;
int _deviceState;
bool isDisconnecting = false;
Map<String, Color> colors = {
'onBorderColor': Colors.green,
'offBorderColor': Colors.red,
'neutralBorderColor': Colors.transparent,
'onTextColor': Colors.green[700],
'offTextColor': Colors.red[700],
'neutralTextColor': Colors.blue,
};
// To track whether the device is still connected to Bluetooth
bool get isConnected => connection != null && connection.isConnected;
// Define some variables, which will be required later
List<BluetoothDevice> _devicesList = [];
BluetoothDevice _device;
bool _connected = false;
bool _isButtonUnavailable = false;
#override
void initState() {
super.initState();
// Get current state
FlutterBluetoothSerial.instance.state.then((state) {
setState(() {
_bluetoothState = state;
});
});
_deviceState = 0; // neutral
// If the bluetooth of the device is not enabled,
// then request permission to turn on bluetooth
// as the app starts up
enableBluetooth();
// Listen for further state changes
FlutterBluetoothSerial.instance
.onStateChanged()
.listen((BluetoothState state) {
setState(() {
_bluetoothState = state;
if (_bluetoothState == BluetoothState.STATE_OFF) {
_isButtonUnavailable = true;
}
getPairedDevices();
});
});}
#override
void dispose() {
// Avoid memory leak and disconnect
if (isConnected) {
isDisconnecting = true;
connection.dispose();
connection = null;
}
super.dispose();}
// Request Bluetooth permission from the user
Future<void> enableBluetooth() async {
// Retrieving the current Bluetooth state
_bluetoothState = await FlutterBluetoothSerial.instance.state;
// If the bluetooth is off, then turn it on first
// and then retrieve the devices that are paired.
if (_bluetoothState == BluetoothState.STATE_OFF) {
await FlutterBluetoothSerial.instance.requestEnable();
await getPairedDevices();
return true;
} else {
await getPairedDevices();
}
return false;}
// For retrieving and storing the paired devices
// in a list.
Future<void> getPairedDevices() async {
List<BluetoothDevice> devices = [];
// To get the list of paired devices
try {
devices = await _bluetooth.getBondedDevices();
} on PlatformException {
print("Error");}
// It is an error to call [setState] unless [mounted] is true.
if (!mounted) {
return;}
// Store the [devices] list in the [_devicesList] for accessing
// the list outside this class
setState(() {
_devicesList = devices;
});}
// Now, its time to build the UI
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("Pair Bluetooth Device"),
backgroundColor: Colors.green[900],
actions: <Widget>[
FlatButton.icon(
icon: Icon(
Icons.refresh,
color: Colors.white,
),
label: Text(
"Refresh",
style: TextStyle(
color: Colors.white,
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
splashColor: Colors.deepPurple,
onPressed: () async {
// So, that when new devices are paired
// while the app is running, user can refresh
// the paired devices list.
await getPairedDevices().then((_) {
show('Device list refreshed');
});
},
),
],
),
body: Container(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Visibility(
visible: _isButtonUnavailable &&
_bluetoothState == BluetoothState.STATE_ON,
child: LinearProgressIndicator(
backgroundColor: Colors.yellow,
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(
'Enable Bluetooth',
style: TextStyle(
color: Colors.black,
fontSize: 16,
),
),
),
Switch(
value: _bluetoothState.isEnabled,
onChanged: (bool value) {
future() async {
if (value) {
await FlutterBluetoothSerial.instance
.requestEnable();
} else {
await FlutterBluetoothSerial.instance
.requestDisable();
}
await getPairedDevices();
_isButtonUnavailable = false;
if (_connected) {
_disconnect();
}
}
future().then((_) {
setState(() {});
});
},
)
],
),
),
Stack(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text(
"PAIRED DEVICES",
style: TextStyle(fontSize: 24, color: Colors.blue,
fontFamily: 'RussoOne'
),
textAlign: TextAlign.center,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Device:',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
DropdownButton(
items: _getDeviceItems(),
onChanged: (value) =>
setState(() => _device = value),
value: _devicesList.isNotEmpty ? _device : null,
),
ElevatedButton(
onPressed: _isButtonUnavailable
? null
: _connected ? _disconnect : _connect,
child:
Text(_connected ? 'Disconnect' : 'Connect'),
),
],
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Card(
shape: RoundedRectangleBorder(
side: new BorderSide(
color: _deviceState == 0
? colors['neutralBorderColor']
: _deviceState == 1
? colors['onBorderColor']
: colors['offBorderColor'],
width: 3,
),
borderRadius: BorderRadius.circular(4.0),
),
elevation: _deviceState == 0 ? 4 : 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
"DEVICE 1",
style: TextStyle(
fontSize: 20,
color: _deviceState == 0
? colors['neutralTextColor']
: _deviceState == 1
? colors['onTextColor']
: colors['offTextColor'],
),
),
),
TextButton(
onPressed: _connected
? _sendOnMessageToBluetooth
: null,
child: Text("ON"),
),
TextButton(
onPressed: _connected
? _sendOffMessageToBluetooth
: null,
child: Text("OFF"),
),
],
),
),
),
),
],
),
Container(
color: Colors.blue,
),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"NOTE: If you cannot find the device in the list, please pair the device by going to the bluetooth settings",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
SizedBox(height: 15),
TextButton.icon(
//color: Colors.blueAccent,
style: TextButton.styleFrom(
elevation: 2,
backgroundColor: Colors.blueAccent,
),
icon: Icon(Icons.bluetooth,
color: Colors.white,
),
label: Text("Settings",
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white
),
),
onPressed: () {
FlutterBluetoothSerial.instance.openSettings();
},
),
SizedBox(height: 15),
TextButton(
//color: Colors.black,
style: TextButton.styleFrom(
backgroundColor: Colors.black,
),
child: Text("Home",
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white
),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
)
],
),
),
),
);}
// Create the List of devices to be shown in Dropdown Menu
List<DropdownMenuItem<BluetoothDevice>> _getDeviceItems() {
List<DropdownMenuItem<BluetoothDevice>> items = [];
if (_devicesList.isEmpty) {
items.add(DropdownMenuItem(
child: Text('NONE'),
));
} else {
_devicesList.forEach((device) {
items.add(DropdownMenuItem(
child: Text(device.name),
value: device,
));
});
}
return items;}
// Method to connect to bluetooth
void _connect() async {
setState(() {
_isButtonUnavailable = true;
});
if (_device == null) {
show('No device selected');
} else {
if (!isConnected) {
await BluetoothConnection.toAddress(_device.address)
.then((_connection) {
print('Connected to the device');
connection = _connection;
setState(() {
_connected = true;
});
connection.input.listen(null).onDone(() {
if (isDisconnecting) {
print('Disconnecting locally!');
} else {
print('Disconnected remotely!');
}
if (this.mounted) {
setState(() {});
}
});
}).catchError((error) {
print('Cannot connect, exception occurred');
print(error);
});
show('Device connected');
setState(() => _isButtonUnavailable = false);
}} }
// void _onDataReceived(Uint8List data) {
// // Allocate buffer for parsed data
// int backspacesCounter = 0;
// data.forEach((byte) {
// if (byte == 8 || byte == 127) {
// backspacesCounter++;
// }
// });
// Uint8List buffer = Uint8List(data.length - backspacesCounter);
// int bufferIndex = buffer.length;
// // Apply backspace control character
// backspacesCounter = 0;
// for (int i = data.length - 1; i >= 0; i--) {
// if (data[i] == 8 || data[i] == 127) {
// backspacesCounter++;
// } else {
// if (backspacesCounter > 0) {
// backspacesCounter--;
// } else {
// buffer[--bufferIndex] = data[i];
// }
// }
// }
// }
// Method to disconnect bluetooth
void _disconnect() async {
setState(() {
_isButtonUnavailable = true;
_deviceState = 0;
});
await connection.close();
show('Device disconnected');
if (!connection.isConnected) {
setState(() {
_connected = false;
_isButtonUnavailable = false;
});
}}
// Method to send message,
// for turning the Bluetooth device on
void _sendOnMessageToBluetooth() async {
connection.output.add(utf8.encode("1" + "\r\n"));
await connection.output.allSent;
show('Device Turned On');
setState(() {
_deviceState = 1; // device on
});}
// Method to send message,
// for turning the Bluetooth device off
void _sendOffMessageToBluetooth() async {
connection.output.add(utf8.encode("0" + "\r\n"));
await connection.output.allSent;
show('Device Turned Off');
setState(() {
_deviceState = -1; // device off
});}
// Method to show a Snackbar,
// taking message as the text
Future show(
String message, {
Duration duration: const Duration(seconds: 3),
}) async {
await new Future.delayed(new Duration(milliseconds: 100));
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content:Text(
message,
),
duration: duration,
),
); }}
I have searched a lot about these errors on internet but didn't find a satisfactory solution.
Please solve this problem.
I will be very grateful.
Thanks in advance.
Try making the call conditional (using '?.') or adding a null check to the target ('!').
_scaffoldKey.currentState?.showSnackBar(
SnackBar(
content:Text(
message,
),
duration: duration,
),
In my Flutter app I'm using audioplayers: ^0.17.0 to play music. When I play music and want to leave the page I want to stop playing music. For that purpose I'm using dispose(). And it looks like it is working. The problem that I'm getting is that I've got an error in the console. I think it is because I'm using async, but I'm not sure how to fix it. Or maybe there is a different solution that I can use for this purpose. Any suggestions?
Here are my code and error:
class _MyAppState extends State<HomeApp> {
var currentPageValue = 0;
double currentPage = 0;
PageController pageController = PageController(initialPage: 0);
AudioPlayer audioPlayer = new AudioPlayer();
#override
void initState() {
super.initState();
pageController.addListener(() {
if (pageController.page == pageController.page.roundToDouble()) {
setState(() {
currentPage = pageController.page;
});
}
});
}
bool playing = false;
#override
Future<void> dispose() async {
await audioPlayer.stop();
super.dispose();
}
#override
Widget build(BuildContext context) {
final itemsData = Provider.of<ItemsList>(context);
_nextCardHandler() async {
if (pageController.page.toInt() < itemsData.items.length - 1) {
pageController.animateToPage(pageController.page.toInt() + 1,
duration: Duration(milliseconds: 400), curve: Curves.easeIn);
} else {
pageController.animateToPage(0,
duration: Duration(milliseconds: 400), curve: Curves.easeIn);
}
if (playing) {
var res = await audioPlayer.stop();
if (res == 1) {
setState(() {
playing = false;
});
}
}
}
_prevCardHandler() async {
if (pageController.page.toInt() == 0) {
pageController.animateToPage(itemsData.items.length - 1,
duration: Duration(milliseconds: 400), curve: Curves.easeIn);
} else {
pageController.animateToPage(pageController.page.toInt() - 1,
duration: Duration(milliseconds: 400), curve: Curves.easeIn);
}
if (playing) {
var res = await audioPlayer.stop();
if (res == 1) {
setState(() {
playing = false;
});
}
print('stop here');
}
}
void _getAudio(audio) async {
if (playing) {
var res = await audioPlayer.pause();
if (res == 1) {
setState(() {
playing = false;
});
}
print('pause uuuu');
} else {
var res = await audioPlayer.play(audio, isLocal: true);
await audioPlayer.setReleaseMode(ReleaseMode.LOOP);
if (res == 1) {
print('play 999');
setState(() {
playing = true;
});
}
}
}
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColor,
title: Text(
itemsData.items[currentPage.round()].title,
),
iconTheme: IconThemeData(color: Theme.of(context).accentColor),
),
drawer: AppDrawer(),
body: PageView.builder(
controller: pageController,
itemCount: itemsData.items.length,
itemBuilder: (ctx, int itemIndex) {
return Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: NetworkImage(itemsData.items[itemIndex].image),
fit: BoxFit.cover,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
child: IconButton(
icon: Icon(Icons.favorite_border),
color: Theme.of(context).accentColor,
iconSize: 40,
onPressed: () {},
),
),
],
),
),
Expanded(
child: Padding(
padding: EdgeInsets.all(20),
),
),
Container(
color: Colors.black54,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
SizedBox(
child: IconButton(
icon: Icon(Icons.arrow_left_sharp),
color: Theme.of(context).accentColor,
iconSize: 80,
onPressed: _prevCardHandler,
),
),
SizedBox(
child: IconButton(
icon: Icon(playing == false
? Icons.play_circle_fill_outlined
: Icons.pause_circle_filled_outlined),
color: Theme.of(context).accentColor,
iconSize: 80,
onPressed: () =>
_getAudio(itemsData.items[itemIndex].audio),
),
),
SizedBox(
child: IconButton(
icon: Icon(Icons.arrow_right_sharp),
color: Theme.of(context).accentColor,
iconSize: 80,
onPressed: _nextCardHandler,
),
),
],
),
),
],
),
);
},
),
);
}
}
enter image description here
According to this link.
You can run asynchronous events after calling super.dispose() first. So in your case
#override
Future<void> dispose() async {
super.dispose(); //change here
await audioPlayer.stop();
}
I have 2 screens and I am trying to achieve understand how to achieve page state. For example, in the below screen, I have 4 options, and all of them take the user to the same screen the only difference is API getting called for each of them is different to build a list. I am trying to handle back arrow action, and that's where I am having issues.
Use Case -
When user is on screen 2 he is playing the song, now on back press song continues to play. Now when the user again chooses the same option from screen 1 I want to show the same list without reload and selection. If user selects any other option it should behave normal, which is working.
Solution -
I can hardcode loaded songs list and send back to screen 1 and then again get that back with the selection but this will take lot of resources.
AutomaticKeepAliveClientMixin i tried this tutorial but that didn't help or kept state active.
PageStorage is 3rd option i saw but i found majority of the time this is being used on app where we have a tab.
Screen 1 -
class Dashboard extends StatefulWidget {
int playingId;
Dashboard({this.playingId});
#override
_DashboardState createState() => _DashboardState(playingId);
}
class _DashboardState extends State<Dashboard> {
String appname;
int playingId = 0;
_DashboardState(this.playingId);
// print('${playingId}');
#override
void initState() {
appname="";
// playingId=0;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: AppColors.darkBlue,
centerTitle: true,
title: Text("Tirthankar",
style: TextStyle(color: Colors.white),),
),
backgroundColor: AppColors.styleColor,
body: Column(
children: <Widget>[
// SizedBox(height: 5),
Padding(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CustomGridWidget(
child: Icon(
Icons.file_download,
size: 100,
color: AppColors.styleColor,
),
// image: 'assets/bhaktambar.png',
sizew: MediaQuery.of(context).size.width * .4,
sizeh: MediaQuery.of(context).size.width * .5,
borderWidth: 2,
label: "Bhakti",
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ListPage(appname: "Kids",playingId: playingId,),
),
);
},
),
CustomGridWidget(
child: Icon(
Icons.file_download,
size: 100,
color: AppColors.styleColor,
),
// image: 'assets/bhaktambar.png',
sizew: MediaQuery.of(context).size.width * .4,
sizeh: MediaQuery.of(context).size.width * .5,
borderWidth: 2,
label: "Kids",
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ListPage(appname: "Kids",playingId: playingId,),
),
);
},
),
],
),
),
Padding(
padding: const EdgeInsets.only(
left: 20,
right: 20,
bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CustomGridWidget(
child: Icon(
Icons.favorite,
size: 100,
color: AppColors.styleColor,
),
// image: 'assets/kids.jpg',
sizew: MediaQuery.of(context).size.width * .4,
sizeh: MediaQuery.of(context).size.width * .5,
borderWidth: 2,
label: "Favorite",
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ListPage(appname: "Songs"),
),
);
},
),
Align(
alignment: Alignment.center,
child: CustomGridWidget(
child: Icon(
Icons.book,
size: 100,
color: AppColors.styleColor,
),
// image: 'assets/vidyasagar.jpg',
sizew: MediaQuery.of(context).size.width * .4,
sizeh: MediaQuery.of(context).size.width * .5,
borderWidth: 2,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ListPage(appname: "Bhajan"),
),
);
},
),
),
],
),
),
]
),
);
}
Material boxTiles(IconData icon, String name){
return Material(
color: AppColors.mainColor,
elevation: 14.0,
shadowColor: AppColors.styleColor,
borderRadius: BorderRadius.circular(24.0),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child:Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: (){print("tapped"); /* or any action you want */ },
child: Container(
width: 130.0,
height: 10.0,
color : Colors.transparent,
), // container
), //
//Text
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(name,
style:TextStyle(
color: AppColors.styleColor,
fontSize: 20.0,
)
),
),
//Icon
Material(
color: AppColors.styleColor,
borderRadius: BorderRadius.circular(50.0),
child: Padding(padding: const EdgeInsets.all(10.0),
child: Icon(icon, color: AppColors.lightBlue,size: 30,),
),
),
],
)
],
)
),
)
);
}
}
Screen 2 -
// import 'dart:js';
class ListPage extends StatefulWidget {
String appname;
int playingId;
ListPage({this.appname,this.playingId});
#override
_ListPageState createState() => _ListPageState(appname,playingId);
}
class _ListPageState extends State<ListPage>
with SingleTickerProviderStateMixin,AutomaticKeepAliveClientMixin<ListPage> {
String appname;
int playingId;
bool isPlaying = false;
_ListPageState(this.appname,playingId);
// List<MusicModel> _list1;
List<MusicData> _list;
var _value;
int _playId;
int _songId;
String _playURL;
bool _isRepeat;
bool _isShuffle;
bool _isFavorite;
String _startTime;
String _endTime;
AnimationController _controller;
Duration _duration = new Duration();
Duration _position = new Duration();
final _random = new Random();
AudioPlayer _audioPlayer = AudioPlayer();
#override
void initState() {
_playId = 0;
// _list1 = MusicModel.list;
this._fileUpdate();
// _list = _list1;
_controller =
AnimationController(vsync: this, duration: Duration(microseconds: 250));
_value = 0.0;
_startTime = "0.0";
_endTime = "0.0";
_isRepeat = false;
_isShuffle = false;
_isFavorite = false;
_audioPlayer.onAudioPositionChanged.listen((Duration duration) {
setState(() {
// _startTime = duration.toString().split(".")[0];
_startTime = duration.toString().split(".")[0];
_duration = duration;
// _position = duration.toString().split(".")[0];
});
});
_audioPlayer.onDurationChanged.listen((Duration duration) {
setState(() {
_endTime = duration.toString().split(".")[0];
_position = duration;
});
});
_audioPlayer.onPlayerCompletion.listen((event) {
setState(() {
isPlaying = false;
_position = _duration;
if (_isRepeat) {
_songId = _songId;
} else {
if (_isShuffle) {
var element = _list[_random.nextInt(_list.length)];
_songId = element.id;
} else {
_songId = _songId + 1;
}
}
_player(_songId);
});
});
super.initState();
}
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: AppColors.mainColor,
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Dashboard(playingId: _songId),
),
);
},
),
title: Text(
appname,
style: TextStyle(color: AppColors.styleColor),
),
),
backgroundColor: AppColors.mainColor,
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(24.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CustomButtonWidget(
child: Icon(
Icons.favorite,
color: AppColors.styleColor,
),
size: 50,
onTap: () {},
),
CustomButtonWidget(
image: 'assets/logo.jpg',
size: 100,
borderWidth: 5,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => DetailPage(),
),
);
},
),
CustomButtonWidget(
child: Icon(
Icons.menu,
color: AppColors.styleColor,
),
size: 50,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => HomePage(),
),
);
},
)
],
),
),
slider(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
_isRepeat ? Icons.repeat_one : Icons.repeat,
color: _isRepeat ? Colors.brown : AppColors.styleColor,
),
onPressed: () {
if (_isRepeat) {
_isRepeat = false;
} else {
_isRepeat = true;
}
},
),
IconButton(
icon: Icon(
isPlaying ? Icons.pause : Icons.play_arrow,
color: AppColors.styleColor,
),
onPressed: () {
if (isPlaying) {
_audioPlayer.pause();
setState(() {
isPlaying = false;
});
} else {
if (!isPlaying){
_audioPlayer.resume();
setState(() {
isPlaying = true;
});
}
}
}),
IconButton(
icon: Icon(
Icons.stop,
color: AppColors.styleColor,
),
onPressed: () {
if (isPlaying){
_audioPlayer.stop();
setState(() {
isPlaying = false;
_duration = new Duration();
});
}
// isPlaying = false;
}),
IconButton(
icon: Icon(
Icons.shuffle,
color:
_isShuffle ? Colors.brown : AppColors.styleColor,
),
onPressed: () {
if (_isShuffle) {
_isShuffle = false;
} else {
_isShuffle = true;
}
}),
],
),
),
Expanded(
//This is added so we can see overlay else this will be over button
child: ListView.builder(
physics:
BouncingScrollPhysics(), //This line removes the dark flash when you are at the begining or end of list menu. Just uncomment for
// itemCount: _list.length,
itemCount: _list == null ? 0 : _list.length,
padding: EdgeInsets.all(12),
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
_songId = index;
_player(index);
},
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
//This below code will change the color of sected area or song being played.
decoration: BoxDecoration(
color: _list[index].id == _playId
? AppColors.activeColor
: AppColors.mainColor,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
//End of row color change
child: Padding(
padding: const EdgeInsets.all(
16), //This will all padding around all size
child: Row(
mainAxisAlignment: MainAxisAlignment
.spaceBetween, //This will allign button to left, else button will be infront of name
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_list[index].title,
style: TextStyle(
color: AppColors.styleColor,
fontSize: 16,
),
),
Text(
_list[index].album,
style: TextStyle(
color: AppColors.styleColor.withAlpha(90),
fontSize: 16,
),
),
],
),
IconButton(
icon: Icon(_isFavorite
? Icons.favorite
: Icons.favorite_border),
onPressed: () {
if (_isFavorite) {
_isFavorite = false;
} else {
_isFavorite = true;
}
})
//Diabled Play button and added fav button.
// CustomButtonWidget(
// //This is Play button functionality on list page.
// child: Icon(
// _list[index].id == _playId
// ? Icons.pause
// : Icons.play_arrow,
// color: _list[index].id == _playId
// ? Colors.white
// : AppColors.styleColor,
// ),
// size: 50,
// isActive: _list[index].id == _playId,
// onTap: () async {
// _songId = index;
// _player(index);
// },
// )
],
),
),
),
);
},
),
)
],
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppColors.mainColor.withAlpha(0),
AppColors.mainColor,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
)),
),
)
],
),
// floatingActionButton: FloatingActionButton(
// child: Icon(Icons.music_note),
// onPressed: () async { // String filePath = await FilePicker.getFilePath();
// int status = await _audioPlayer.play("https://traffic.libsyn.com/voicebot/Jan_Konig_on_the_Jovo_Open_Source_Framework_for_Voice_App_Development_-_Voicebot_Podcast_Ep_56.mp3");
// if (status == 1){
// setState(() {
// isPlaying = true;
// });
// }
// },
// )
);
}
Widget slider() {
return Slider(
activeColor: AppColors.styleColor,
inactiveColor: Colors.lightBlue,
value: _duration.inSeconds.toDouble(),
min: 0.0,
max: _position.inSeconds.toDouble(),
divisions: 10,
onChangeStart: (double value) {
print('Start value is ' + value.toString());
},
onChangeEnd: (double value) {
print('Finish value is ' + value.toString());
},
onChanged: (double value) {
setState(() {
seekToSecond(value.toInt());
value = value;
});
});
}
Future<Void> _fileUpdate() async {
String url =
"azonaws.com/input.json";
String arrayObjsText = "";
try {
eos.Response response;
Dio dio = new Dio();
response = await dio.get(url,options: Options(
responseType: ResponseType.plain,
),);
arrayObjsText = response.data;
print(response.data.toString());
} catch (e) {
print(e);
}
var tagObjsJson = jsonDecode(arrayObjsText)['tags'] as List;
this.setState(() {
_list = tagObjsJson.map((tagJson) => MusicData.fromJson(tagJson)).toList();
});
// return _list;
// print(_list);
}
Future<void> _player(int index) async {
if (isPlaying) {
if (_playId == _list[index].id) {
int status = await _audioPlayer.pause();
if (status == 1) {
setState(() {
isPlaying = false;
});
}
} else {
_playId = _list[index].id;
_playURL = _list[index].songURL;
_audioPlayer.stop();
int status = await _audioPlayer.play(_playURL);
if (status == 1) {
setState(() {
isPlaying = true;
});
}
}
} else {
_playId = _list[index].id;
_playURL = _list[index].songURL;
int status = await _audioPlayer.play(_playURL);
if (status == 1) {
setState(() {
isPlaying = true;
});
}
}
}
String _printDuration(Duration duration) {
String twoDigits(int n) {
if (n >= 10) return "$n";
return "0$n";
}
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
}
void seekToSecond(int second) {
Duration newDuration = Duration(seconds: second);
_audioPlayer.seek(newDuration);
}
}
PageStorage is 3rd option i saw but i found majority of the time this is being used on app where we have a tab.
You still can use this approach with what you want, with or without Tab/ bottom navigation bar.
PageViewClass
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with SingleTickerProviderStateMixin{
PageController _pageController;
#override
void initState() {
super.initState();
_pageController = PageController();
}
#override
void dispose() {
super.dispose();
_pageController?.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: PageView(
controller: _pageController,
physics: NeverScrollableScrollPhysics(), // so the user cannot scroll, only animating when they select an option
children: <Widget>[
Dashboard(playingId: 1, key: PageStorageKey<String>('MyPlayList'), pageController: _pageController), //or the name you want, but you need to give them a key to all the child so it can save the Scroll Position
ListPage(appname: "FirstButton",playingId: 1, key: PageStorageKey<String>('FirstButton'), pageController: _pageController),
ListPage(appname: "SecondButton",playingId: 1, key: PageStorageKey<String>('SecondButton'), pageController: _pageController),
ListPage(appname: "ThirdButton",playingId: 1, key: PageStorageKey<String>('ThirdButton'), pageController: _pageController),
ListPage(appname: "FourthButton",playingId: 1, key: PageStorageKey<String>('FourthButton'), pageController: _pageController)
],
),
)
);
}
}
Now you pass the PageController to all children (add a key and PageController attribute to Screen 1 and 2) and in DashBoard (Screen 1) you can change the onTap of the buttons from the MaterialRoute to this
onTap: () => widget.pageController.jumpToPage(x), //where x is the index of the children of the PageView you want to see (between 0 and 4 in this case)
In Screen 2 you wrap all your Scaffold with a WillPopScope so when the user tap back instead of closing the route it goes back to the Dashboard Widget at index 0
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
widget.pageController.jumpToPage(0); // Move back to dashboard (index 0)
return false;
}
child: Scaffold(...)
);
}
You can use other methods of PageController if you want some effects like animations (animateTo, nextPage, previousPage, etc.)
I am new to flutter and trying to solve the below issue, in the first screenshot I have labelStart line 127 value as 1.21, when i pass that value using the variable i get renderflex error, if i am using hardcoded i don't get any error. Not sure what i am doing wrong. I tried adding Expanded after reading few posts online but that didn't help. Can someone please guide me on what mistake i am doing here?
class _ListPageState extends State<ListPage> with SingleTickerProviderStateMixin {
List<MusicModel> _list;
var _value;
int _playId;
String _playURL;
bool isPlaying = false;
String _startTime;
String _endTime;
AnimationController _controller;
AudioPlayer _audioPlayer = AudioPlayer();
#override
void initState() {
_playId = 0;
_list = MusicModel.list;
_controller = AnimationController(vsync: this,duration: Duration(microseconds: 250));
_value = 0.0;
_startTime="0.0";
_endTime="0.0";
super.initState();
_audioPlayer.onAudioPositionChanged.listen((Duration duration) {
setState(() {
_startTime = duration.toString().split(".")[0];
});
});
_audioPlayer.onDurationChanged.listen((Duration duration) {
setState(() {
_endTime = duration.toString().split(".")[0];
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: AppColors.mainColor,
centerTitle: true,
title: Text("Skin - Flume",
style: TextStyle(color: AppColors.styleColor),),
),
backgroundColor: AppColors.mainColor,
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(24.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CustomButtonWidget(
child: Icon(
Icons.favorite,
color: AppColors.styleColor,
),
size: 50,
onTap: (){
},
),
CustomButtonWidget(
image: 'assets/logo.jpg',
size: 100,
borderWidth: 5,
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => DetailPage(),
),
);
},
),
CustomButtonWidget(
child: Icon(
Icons.menu,
color: AppColors.styleColor,
),
size: 50,
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => HomePage(),
),
);
},
)
],
),
),
//Progress bar section
// Expanded(child: SizedBox()),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: CustomProgressWidget(
value: _value,
labelStart: "1.21",
labelend: "2.34",
),
),
// Expanded(child: SizedBox()),
Expanded( //This is added so we can see overlay else this will be over button
child: ListView.builder(
physics: BouncingScrollPhysics(),//This line removes the dark flash when you are at the begining or end of list menu. Just uncomment for
itemCount: _list.length,
padding: EdgeInsets.all(12),
itemBuilder: (context,index){
return GestureDetector(
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => DetailPage(),
),
);
},
child: AnimatedContainer(
duration: Duration(milliseconds: 500),
//This below code will change the color of sected area or song being played.
decoration: BoxDecoration(
color: _list[index].id == _playId
? AppColors.activeColor
: AppColors.mainColor,
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
//End of row color change
child: Padding(
padding: const EdgeInsets.all(16), //This will all padding around all size
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //This will allign button to left, else button will be infront of name
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_list[index].title,
style: TextStyle(
color: AppColors.styleColor,
fontSize: 16,
),
),
Text(
_list[index].album,
style: TextStyle(
color: AppColors.styleColor.withAlpha(90),
fontSize: 16,
),
),
],
),
CustomButtonWidget( //This is Play button functionality on list page.
child: Icon(
_list[index].id == _playId
? Icons.pause
: Icons.play_arrow,
color: _list[index].id == _playId
? Colors.white
: AppColors.styleColor,
),
size: 50,
isActive: _list[index].id == _playId,
onTap: () async {
if (isPlaying){
if (_playId == _list[index].id){
int status = await _audioPlayer.pause();
if (status == 1){
setState(() {
isPlaying = false;
});
}
} else {
_playId = _list[index].id;
_playURL = _list[index].songURL;
_audioPlayer.stop();
int status = await _audioPlayer.play(_playURL);
if (status == 1){
setState(() {
isPlaying = true;
});
}
}
// int status = await _audioPlayer.pause();
// if (status == 1){
// setState(() {
// isPlaying = false;
// });
// }
} else {
_playId = _list[index].id;
_playURL = _list[index].songURL;
int status = await _audioPlayer.play(_playURL);
if (status == 1){
setState(() {
isPlaying = true;
});
}
} // String filePath = await FilePicker.getFilePath();
},
// onTap: (){
// setState(() {
// _playId = _list[index].id;
// });
// },
)
],
),
),
),
);
},
),
)
],
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 50,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppColors.mainColor.withAlpha(0),
AppColors.mainColor,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
)
),
),
)
],
),
);
}
}
After changing line 1.27 with a dynamic value variable.
You have to wrap you Column in a scrollview like SingleChildScrollView or ListView. This error occurs when the items in column take more space than available.
I had the same problem, and my problem was my variable extracted of my state it took too long in show and showed first the widget after the variable.
In my case use Getx, and fixed for this way:
My old code:
GetX<UserController>(
builder: (_){
return Text(_.user.name);
}
},
),
My new code
GetX<UserController>(
builder: (_){
if(_.user.email != null){
return Text(_.user.name);
}else{
return Text('Loading....');
}
},
),