I'm looking to highlight a button from a grid when it's pushed.
Unfortunately, when I do so, the whole column lights up. As I'm new to flutter/Dart and to coding in general, I'm not sure if my problème is my lack of logic or something that I wouldn't know about that coding language?
The home page :
import 'package:flutter/material.dart';
import 'package:sequencer_n_lignes/utilities/sequence_class.dart';
class Home extends StatefulWidget {
#override
_Home createState() => _Home();
}
class _Home extends State<Home> {
int i = 0, y = 0, indexTempo = 0;
int countChanel = 0, countBtn = 0;
bool isPlaying = false;
List<Button> btnList = List();
List<Chanel> chanelList = List();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.grey[800],
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(20, 10, 20, 10),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 5,
spreadRadius: 1,
)
],
color: Colors.grey[900],
border: Border.all(
color: Colors.white,
width: 0.5,
)),
child: Row(
children: <Widget>[
/*__________________________________________ADD/REMOVE BUTTONS___________________*/
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
for (i = 0; i < 4; i++) {
btnList.removeLast();
countBtn--;
}
setState(() {});
},
),
Text('BUTTONS: $countBtn'),
IconButton(
icon: Icon(
Icons.add,
),
onPressed: () {
for (i = 0; i < 4; i++) {
btnList.add(Button(
id: countBtn,
onColor: Colors.blue,
offColor: Colors.grey[900],
state: false));
countBtn++;
}
setState(() {});
},
),
],
), //
/*_________________________________________ADD/REMOVE CHANEL___________________*/
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
chanelList.removeLast();
countChanel--;
setState(() {});
},
),
Text('CHANEL: $countChanel'),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
chanelList.add(
Chanel(id: countChanel, buttonList: btnList));
countChanel++;
setState(() {});
},
),
],
),
SizedBox(
width: 30,
),
/*_____________________________________________CONTROLS___________________*/
Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.play_arrow,
color: (isPlaying) ? Colors.green : Colors.white,
),
onPressed: () {
if (isPlaying)
isPlaying = false;
else
isPlaying = true;
setState(() {});
},
),
IconButton(
icon: Icon(
Icons.stop,
color: (isPlaying) ? Colors.white : Colors.red[900],
),
onPressed: () {
if (isPlaying)
isPlaying = false;
else
isPlaying = true;
setState(() {});
},
),
IconButton(
icon: Icon(
Icons.refresh,
color: Colors.white,
),
onPressed: () {
for (i = 0; i < chanelList.length; i++) {
for (y = 0; y < btnList.length; y++) {
chanelList[i].buttonList[y].state = false;
}
}
setState(() {});
},
),
RaisedButton.icon(
icon: Icon(
Icons.details,
color: Colors.white,
),
label: Text('OK'),
color: Colors.red[900],
onPressed: () {
setState(() {});
},
)
],
),
],
),
),
/*__________________________________________ GRID ___________________*/
Column(
children: List.generate(countChanel, (indexChanel) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 5, 0, 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(countBtn, (indexBtn) {
return Padding(
padding: EdgeInsets.fromLTRB(3, 0, 3, 0),
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 0.1,
spreadRadius: 0.1,
),
],
border: Border.all(
color: Colors.white,
width: 0.5,
),
),
width: 80,
height: 80,
//THATS WHERE THE PROBLEM IS///////////////////////////
child: FlatButton(
// child: Text(
// '${chanelList[indexChanel].id.toString()} \n${chanelList[indexChanel].buttonList[indexBtn].id.toString()}\n$indexChanel-$indexBtn\n${chanelList[indexChanel].buttonList[indexBtn].state}'),
color: (chanelList[indexChanel]
.buttonList[indexBtn]
.state)
? chanelList[indexChanel]
.buttonList[indexBtn]
.onColor
: chanelList[indexChanel]
.buttonList[indexBtn]
.offColor,
onPressed: () {
if (chanelList[indexChanel]
.buttonList[indexBtn]
.state) {
chanelList[indexChanel]
.buttonList[indexBtn]
.state = false;
} else {
chanelList[indexChanel]
.buttonList[indexBtn]
.state = true;
}
setState(() {});
},
),
),
);
}),
),
);
}),
),
],
),
),
);
}
}
The class
class Button {
int id;
Color onColor = Colors.red[900], offColor = Colors.grey[900];
Color actualColor;
bool state = false;
Button({this.id, this.onColor, this.offColor, this.state});
}
class Chanel {
int id;
List<Button> buttonList;
Chanel({this.id, this.buttonList});
}
Screen shot of the app
Pretty big code but I think the problem is that whenever you add a new Channel, you are giving it an existen buttonList. Try creating a new buttonList when you add a new Channel
chanelList.add(
Chanel(
id: countChanel,
// Here is your problem, the reference to the buttons is the same
// in all channels. Try creating new buttons for every channel
buttonList: btnList,
),
);
I'll go over some of the programming logic improvements 1st and then explain why you are getting unexpected results.
1) Color actualColor inside Button class is never used, remove it.
2) Unless each button is going to have different onColor and offColor I suggest moving those two out of the Button class or at least declare them as static. You are needlessly instantiating them over and over again when I'm guessing you only need those once, this is a very tiny memory improvement (especially since you won't have thousands of buttons) but more importantly removing those from the Button class or making them static will make your code easier to read and understand, as well as cut down the number of arguments needed to pass to the constructor (again cleaner code).
3) Your loop counters "i" and "y", declare them where they are needed. Reduce the scope of the variable so that it is only visible in the scope where it is used. There are many... many reasons for doing so, in a nutshell when a larger scope than necessary is used, code becomes less readable, harder to maintain, and more likely to reference unintended variables.
Now for your actual problem. The problem isn't with if/else statements it has to do with lists and how they are handled in memory.
Going back to my 3rd point above, always use the smallest scope possible.
You are declaring your btnList here
class _Home extends State<Home> {
int i = 0, y = 0, indexTempo = 0;
int countChanel = 0, countBtn = 0;
bool isPlaying = false;
List<Button> btnList = List();
List<Chanel> chanelList = List();
Later on you are adding that same btnList to different Channels here:
Text('CHANEL: $countChanel'),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
chanelList.add(
Chanel(id: countChanel, buttonList: btnList));
countChanel++;
setState(() {});
},
I suggest going back to basics and learn in general about arrays , lists and pointers. You should also search for deep and shallow copying.
What you've done in the code block above is setting the same btnList to all of the chanelList items.
Lets say you create btnList that has 4 items. Lets say you create channelList that has 2 items. Then channelList[ 0 ].buttonList[ 0 ].state will always be the same as channelList[ 1 ].buttonList[ 0 ].state because they are both pointing to the same Button.
To get this:
Quick and easy fix would be to do something like this:
IconButton(
icon: Icon(Icons.add),
onPressed: () {
List<Button> tmpBtnList = new List<Button>();
for(int i=0; i<btnList.length; i++){
tmpBtnList.add(new Button(id: i,state: false));
}
chanelList.add(
Chanel(id: countChanel, buttonList: tmpBtnList));
countChanel++;
setState(() {});
},
),
Complete code on DartPad.
PS I would also refrain from manually counting list items like you've done, just use the the provided .length.
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 {}
I want to know how to move between pages in flutter introduction screen. To clarify the problem, I want to go back a page when skip button is pressed.
So far I have done this:
class _IntroPageState extends State<IntroPage> {
int currentIndex = 0;
void _onIntroEnd(context) {
getIt<IntroLocalDataSource>().setIntroSeenState(true);
Navigator.of(context).pushReplacementNamed(SignInPage.id);
}
#override
Widget build(BuildContext context) {
final strings = Languages.of(context);
final bodyStyle = Theme.of(context)
.textTheme
.subtitle2
?.copyWith(fontSize: k16TextFontSize);
final titleStyle = Theme.of(context)
.textTheme
.headline1
?.copyWith(fontSize: k20TextFontSize);
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Flexible(
child: Container(
child: IntroductionScreen(
onChange: (index) {
setState(() {
currentIndex = index;
});
},
rtl: true,
globalBackgroundColor: Colors.transparent,
showNextButton: false,
rawPages: strings.introScreenTitles.asMap().entries.map((entry) {
int idx = entry.key;
String val = entry.value;
return Center(
child: IntroCardWidget(
index: idx,
title: val,
bodyStyle: bodyStyle,
titleStyle: titleStyle,
image: Assets.introImages[idx],
description: strings.introScreenDescriptions[idx],
));
}).toList(),
showDoneButton: false,
curve: Curves.fastLinearToSlowEaseIn,
showSkipButton: currentIndex != 0,
skip: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
primary: kLightTextColor,
shape: CircleBorder(),
),
onPressed: () {
setState(() {
currentIndex--; // <<--------- This does not work
});
},
child: Icon(
Icons.keyboard_arrow_left_rounded,
color: Theme.of(context).primaryColor,
)),
dotsDecorator: DotsDecorator(
color: kLightTextColor.withOpacity(.15),
activeSize: Size(20, 10),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
activeColor: kLightTextColor),
controlsPadding: kIsWeb
? const EdgeInsets.all(12.0)
: const EdgeInsets.symmetric(
vertical: Spacings.paddingSm,
horizontal: Spacings.paddingXs),
),
),
),
Container(
constraints: BoxConstraints(
maxHeight: Spacings.margin5Xl, minHeight: Spacings.margin5Xl),
margin: EdgeInsets.only(bottom: Spacings.margin5Xl),
child: currentIndex != 3
? Container()
: ElevatedButton(
onPressed: () => _onIntroEnd(context),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: Spacings.padding5Xl,
vertical: Spacings.paddingSm),
child: Text(
strings.goToVerificationPageBtnText,
style: TextStyle(
fontSize: k16TextFontSize, color: kDarkTextColor),
),
),
style: ElevatedButton.styleFrom(
elevation: 1,
primary: kLightTextColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Spacings.radiusLg),
),
),
),
),
],
);
}
But the page does not change. It seems to make sense, as the index is not passed to the IntroductionScreen widget. So I was wondering how to navigate in these pages as will.
I found a way to do what I wanted.
It could be done with using keys & calling IntroductionScreenState's methods.
After going through the source code of library, it seems it is changing pages using this public method:
Future<void> animateScroll(int page) async {
setState(() => _isScrolling = true);
await _pageController.animateToPage(
max(min(page, getPagesLength() - 1), 0),
duration: Duration(milliseconds: widget.animationDuration),
curve: widget.curve,
);
if (mounted) {
setState(() => _isScrolling = false);
}
}
and also has these methods for going forward & backward:
void next() => animateScroll(_currentPage.round() + 1);
void previous() => animateScroll(_currentPage.round() - 1);
From this point, it was just a matter of calling the methods of this state when needed. This could be done using keys:
GlobalKey<IntroductionScreenState> _introScreenKey =
GlobalKey<IntroductionScreenState>();
IntroductionScreen(
key: _introScreenKey,
skip: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
primary: kLightTextColor,
shape: CircleBorder(),
),
onPressed: () {
_introScreenKey.currentState?.previous(); // <<----- This here
},
child: Icon(
Icons.keyboard_arrow_left_rounded,
color: Theme.of(context).primaryColor,
)),
)
And ofcourse it is pretty easy to navigate directly to any page using the animateScroll().
Since you're using navigator, you should give a try to Navigator.pop()
onPressed: () { Navigator.pop(context); }
here you can find some examples
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();
}
}
I am trying to align the bottom section on the page to center, this shows correctly on a Mobile device but in the web it looks off. How do I arrange all 4 music buttons and text able in the center of the page. I tried Align friand center but both didn't bring those to the center of the widget. My goal is to get a button in the center of page based on page size, if page size is small below code is good but when i maximize browser it doesn't show in center.
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width * 0.7,
// child: Expanded(child: slider()),
child: kIsWeb ? null : slider(),
),
Marquee(
child: Text(inuseAudioinfo.title ?? appname,
softWrap: true,
style: TextStyle(
// color: AppColors.black.withAlpha(90),
color: AppColors.black.withAlpha(150),
fontSize: 16,
)),
),
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.red[300]),
// bottom: BorderSide(color: AppColors.white)
)),
child: Wrap(
spacing: kIsWeb
? MediaQuery.of(context).size.width * 0.1
: 25, // space between two icons
children: <Widget>[
IconButton(
icon: Icon(
inuseAudioinfo.isRepeat
? Icons.repeat_one
: Icons.repeat,
color: inuseAudioinfo.isRepeat
? AppColors.brown
: AppColors.black,
),
onPressed: () {
print("User clicked Repeat one.");
if (inuseAudioinfo.playId != null) {
Duration seekdur = new Duration(seconds: 10);
if (inuseAudioinfo.isRepeat) {
setState(() {
inuseAudioinfo.isRepeat = false;
});
} else {
setState(() {
inuseAudioinfo.isRepeat = true;
});
}
} else {
commonmethod.displayDialog(
context,
"",
"Please select song to play.",
Icon(
Icons.library_music,
size: 100,
color: AppColors.red200,
),
);
}
},
),
IconButton(
icon: Icon(
inuseAudioinfo.isPlaying
? Icons.pause
: Icons.play_arrow,
color: AppColors.black,
),
onPressed: () {
_player(_songId);
}),
IconButton(
icon: Icon(
Icons.stop,
color: AppColors.black,
),
onPressed: () {
if (inuseAudioinfo.isPlaying) {
// _inuseAudioinfo.audioPlayer.stop();
inuseAudioinfo.duration =
new Duration(seconds: 0);
inuseAudioinfo.audioPlayer.stop();
setState(() {
inuseAudioinfo.isPlaying = false;
// position = new Duration(seconds: 0);
// _duration = new Duration();
});
}
// isPlaying = false;
}),
IconButton(
icon: Icon(
Icons.shuffle,
color: inuseAudioinfo.isShuffle
? AppColors.brown
: AppColors.black,
),
onPressed: () {
if (inuseAudioinfo.isShuffle) {
setState(() {
inuseAudioinfo.isShuffle = false;
});
} else {
setState(() {
inuseAudioinfo.isShuffle = true;
});
}
}),
],
),
),
// ),
// ),
],
)
remove Wrap() and use Row(mainAxisAlignment: MainAxisAlignment.center,)
As a follow up to the article of this link. I am working on a Flutter Project in which I want to increase the radius of a circle by means of two buttons.
Now I have partly succeeded, but it does not work quite well yet. I don't really know exactly how to explain this, but I will try my best:
What happened is that as soon as I press the minus button it goes a step smaller. If I press the minus button again, it will become a little smaller again. But as soon as I press the plus again, it remains the same size until I pass the number which was highest.
A video of the problem if its not be clearly explained.
Maybe someone knows how to handle this?
The Code (removed the unnecessary code):
class _AddRayPageState extends State<AddRayPage> {
List<Marker> myMarker = [];
final Set<Circle> circle = {};
GoogleMapController mapController;
int _n = 8;
LatLng startLoc = LatLng(52.0907374, 5.1214201);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Toevoegen'),
),
body: Stack(children: <Widget>[
GoogleMap(
onMapCreated: onMapCreated,
markers: Set.from(myMarker),
initialCameraPosition: CameraPosition(target: startLoc, zoom: 8),
circles: circle,
),
]),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 40.0),
child: Container(
child: Row(
children: <Widget>[
Container(
width: 40.0,
height: 40.0,
child: new FloatingActionButton(
heroTag: "btnAdd",
onPressed: add,
child: new Icon(
Icons.add,
color: Colors.black,
size: 30,
),
backgroundColor: Colors.white,
),
),
new Text('$_n', style: new TextStyle(fontSize: 40.0)),
Container(
width: 40.0,
height: 40.0,
child: new FloatingActionButton(
heroTag: "btnMinus",
onPressed: minus,
child: new Icon(
const IconData(0xe15b, fontFamily: 'MaterialIcons'),
color: Colors.black,
size: 30,
),
backgroundColor: Colors.white,
),
),
],
),
),
),
],
),
);
}
void add() {
setState(() {
_n++;
});
addRadiusToMap(_n);
}
void minus() {
setState(() {
if (_n != 1) _n--;
});
addRadiusToMap(_n);
}
void addRadiusToMap(radius) {
setState(() {
double reciprocal(double d) => 1000 * d;
circle.add(Circle(
circleId: CircleId("1"),
center: startLoc,
radius: reciprocal(radius.toDouble()),
));
});
}
circle is a Set, a Set doesn't allow repeated objects, in addRadiusToMap you're adding a new Circle object but if there is a previous one with the same fields (7 and 8 already existed) it won't add it, I think the widget GoogleMaps doesn't see a change in the Set<Circle> and doesn't update/animate the new Circle, for now try adding circle.clear() before adding if the add return false(returns false and the set is not changed)
void add() {
setState(() {
_n++;
addRadiusToMap(_n);
});
}
void minus() {
if (_n != 1)
setState(() {
_n--;
addRadiusToMap(_n);
});
}
void addRadiusToMap(radius) {
//No purpose in having 2 setState
double reciprocal(double d) => 1000 * d;
circle.clear(); //Maybe clear the set before adding to avoid repeated values
circle.add(Circle(
circleId: CircleId("1"),
center: startLoc,
radius: reciprocal(radius.toDouble()),
));
}
I'm not really sure (I haven't used the Google Maps package) what's the purpose of having a Set<Circle> but as far as I understand the code, the Set is not really updated because you already has those values