Align multiple button in center of flutter webpage - flutter

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,)

Related

Custom keyboard with changed numbers every time in flutter

I am working over my some random dribble ui/ux designs and this design came and I am struggling with creating logic of it about how it will work.
Image Its a secured keyboard for digits password and for otp the numbers are scrambled every time when user uses the app I'm stuck with this part for ages now please if anyone can help it is a unique problem it will definitely help others as well. Check my code as reference below note its not complete code its part of it only the otp keyboard.
class _OtpState extends State<Otp> with SingleTickerProviderStateMixin {
final int time = 180;
AnimationController _controller;
Size _screenSize;
int _currentDigit;
int _firstDigit;
int _secondDigit;
int _thirdDigit;
int _fourthDigit;
int _fifthDigit;
Timer timer;
int totalTimeInSeconds;
bool _hideResendButton;
get _getInputField {
return new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_otpTextField(_firstDigit),
_otpTextField(_secondDigit),
_otpTextField(_thirdDigit),
_otpTextField(_fourthDigit),
_otpTextField(_fifthDigit),
],
);
}
get _getOtpKeyboard {
return new Container(
height: _screenSize.width - 20,
child: new Column(
children: <Widget>[
new Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_otpKeyboardInputButton(
label: "1",
onPressed: () {
_setCurrentDigit(1);
}),
_otpKeyboardInputButton(
label: "2",
onPressed: () {
_setCurrentDigit(2);
}),
_otpKeyboardInputButton(
label: "3",
onPressed: () {
_setCurrentDigit(3);
}),
],
),
),
SizedBox(
height: 20,
),
new Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_otpKeyboardInputButton(
label: "4",
onPressed: () {
_setCurrentDigit(4);
}),
_otpKeyboardInputButton(
label: "5",
onPressed: () {
_setCurrentDigit(5);
}),
_otpKeyboardInputButton(
label: "6",
onPressed: () {
_setCurrentDigit(6);
}),
],
),
),
SizedBox(
height: 20,
),
new Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_otpKeyboardInputButton(
label: "7",
onPressed: () {
_setCurrentDigit(7);
}),
_otpKeyboardInputButton(
label: "8",
onPressed: () {
_setCurrentDigit(8);
}),
_otpKeyboardInputButton(
label: "9",
onPressed: () {
_setCurrentDigit(9);
}),
],
),
),
SizedBox(
height: 20,
),
new Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_otpKeyboardActionButton(
label: new Image.asset(
"assets/cancel.png",
scale: 1.3,
),
onPressed: () {
setState(() {
if (_fifthDigit != null) {
_fifthDigit = null;
} else if (_fourthDigit != null) {
_fourthDigit = null;
} else if (_thirdDigit != null) {
_thirdDigit = null;
} else if (_secondDigit != null) {
_secondDigit = null;
} else if (_firstDigit != null) {
_firstDigit = null;
}
});
}),
_otpKeyboardInputButton(
label: "0",
onPressed: () {
_setCurrentDigit(0);
}),
_otpKeyboardActionButton(
label: new Icon(
Icons.check_rounded,
color: Color(MainAppColor),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreatePin(),
));
}),
],
),
),
Widget _otpKeyboardInputButton({String label, VoidCallback onPressed}) {
return new Material(
color: Colors.transparent,
child: new InkWell(
onTap: onPressed,
borderRadius: new BorderRadius.circular(40.0),
child: new Container(
height: 80.0,
width: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.circle, color: Colors.grey[300]),
child: new Center(
child: new Text(
label,
style: new TextStyle(
fontSize: 30.0,
color: Colors.black,
),
),
),
),
),
);
}
_otpKeyboardActionButton({Widget label, VoidCallback onPressed}) {
return new InkWell(
onTap: onPressed,
borderRadius: new BorderRadius.circular(40.0),
child: new Container(
height: 80.0,
width: 80.0,
decoration:
new BoxDecoration(shape: BoxShape.circle, color: Colors.grey[300]),
child: new Center(
child: label,
),
),
);
}
void _setCurrentDigit(int i) {
setState(() {
_currentDigit = i;
if (_firstDigit == null) {
_firstDigit = _currentDigit;
} else if (_secondDigit == null) {
_secondDigit = _currentDigit;
} else if (_thirdDigit == null) {
_thirdDigit = _currentDigit;
} else if (_fourthDigit == null) {
_fourthDigit = _currentDigit;
} else if (_fifthDigit == null) _fifthDigit = _currentDigit;
// ignore: unused_local_variable
var otp = _firstDigit.toString() +
_secondDigit.toString() +
_thirdDigit.toString() +
_fourthDigit.toString() +
_fifthDigit.toString();
});
}
Future<Null> _startCountdown() async {
setState(() {
_hideResendButton = true;
totalTimeInSeconds = time;
});
_controller.reverse(
from: _controller.value == 0.0 ? 1.0 : _controller.value);
}
void clearOtp() {
_fifthDigit = null;
_fourthDigit = null;
_thirdDigit = null;
_secondDigit = null;
_firstDigit = null;
setState(() {});
}
}
I have the best solution so far for you its still not the best though but it will help a lot. Use pinpad package it will fulfill the random keys task for you easily and you may try your best to customize the keyboard as much as you can.
URL to PinPad Package
Good Luck

setState from child widget (drawer) not updating a widget above it in the tree (FloatingAppBar)

I have a flutter project with a FloatingSearchBar from this library (pub.dev). I have four buttons, one of which is a GestureDetector (which is not really important but explains some behind scenes info).
This all looks like this:
or this:
or one other variation.
These buttons all work fine, although I've spent a lot of time getting them that way. They are toggleable, and their Icons are decided by a variable that can be updated using setState.
There's also, however, this layout:
which should be able to be toggled on and off by this switch/button inside the menu:
It too just updates the offlineMode variable inside a setState. But this setState doesn't update the search bar until I force the bar to update by clicking any of the buttons.
Why is setState not working in this particular circumstance?
Code for search bar:
Widget buildFloatingSearchBar(AsyncSnapshot snapshot) {
const bool isPortrait = true;
return DescribedFeatureOverlay( //Don't worry about these I don't think
featureId: 'search',
tapTarget: Icon(Icons.search),
title: Text('Search'),
description: Text(
'Tap the bar at the top to open the search interface, where you can search for GeoTags by name, approximate location or by author.'),
overflowMode: OverflowMode.extendBackground,
backgroundColor: Theme.of(context).primaryColor,
targetColor: Colors.white,
textColor: Colors.white,
child: FloatingSearchBar(
borderRadius: BorderRadius.all(
Radius.circular(50),
),
progress: loadingSearch,
title: offlineMode //Checking offlineMode variable Should update with setState
? Row(
children: [
Text(
'Geotagger',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
Text(
' - Offline Mode',
style: TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 15,
),
),
],
)
: null,
backgroundColor: Theme.of(context).backgroundColor,
hint: 'Find a GeoTag...', //Shown if offlineMode is off (title is null)
transitionDuration: const Duration(milliseconds: 800),
transitionCurve: Curves.easeInOut,
physics: const BouncingScrollPhysics(),
axisAlignment: isPortrait ? 0.0 : -1.0,
openAxisAlignment: 0.0,
maxWidth: isPortrait ? 600 : 500,
height: compassExpanded ? 62 : 48,
debounceDelay: const Duration(milliseconds: 1500),
onQueryChanged: (inQuery) {
String query = inQuery.trim();
if (offlineMode || query == null || query == '' || query == '#') {
return;
}
if (query.startsWith('#')) {}
setState(() {
loadingSearch = true;
});
// Call your model, bloc, controller here.
Future.delayed(const Duration(seconds: 3), () {
setState(() {
loadingSearch = false;
});
});
},
// Specify a custom transition to be used for
// animating between opened and closed stated.
transition: ExpandingFloatingSearchBarTransition(),
accentColor: Theme.of(context).accentColor,
actions: [
FloatingSearchBarAction.searchToClear(
showIfClosed: false,
),
FloatingSearchBarAction( //This one is to check current GPS state
showIfOpened: false,
child: StreamBuilder<Object>(
stream: Stream.periodic(Duration(seconds: 5), (x) => x),
builder: (context, _) {
return FutureBuilder(
future: Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.medium,
timeLimit: Duration(seconds: 5),
),
builder: (context, compassDir) {
if (compassDir.hasError) {
//print('failure');
return Padding(
padding: const EdgeInsets.only(
right: 7,
bottom: 2,
),
child: Icon(
Icons.wrong_location,
color: Colors.red,
),
);
} else {
return Container(width: 0, height: 0);
}
});
}),
),
FloatingSearchBarAction(
showIfOpened: false,
child: DescribedFeatureOverlay(
featureId: 'toggleLocationSnapping',
tapTarget: Icon(Icons.control_camera),
title: Text('Location Snapping'),
description: Text(
'This button toggles the map mode between snapping (default) and free. When the icon shown is a circle with a line across it, tap it to switch to free mode, and you\'ll be able to move, zoom and rotate the map freely. In snapping mode, you will be snapped to your current location and orientation, and you\'ll also be unable to pan, rotate or zoom (usually).'),
//overflowMode: OverflowMode.extendBackground,
backgroundColor: Theme.of(context).primaryColor,
targetColor: Colors.white,
textColor: Colors.white,
child: CircularButton(
icon: Icon(moveMapToUser
? Icons.location_disabled
: Icons.my_location),
onPressed: () {
setState(() {
moveMapToUser = !moveMapToUser;
rotateMapToUser = false;
});
},
),
),
),
FloatingSearchBarAction(
showIfOpened: false,
child: Visibility(
visible: moveMapToUser,
child: DescribedFeatureOverlay(
featureId: 'rotationAndNorth',
tapTarget: Icon(Icons.screen_rotation),
title: Text('Rotation & Panning Mode'),
description: Text(
'This button has three states. When showing an upward facing arrow in free mode, tap it to orientate the map north, and remain in free mode. When showing a lock symbol in snapping mode, tap it to renable automatic rotation and prevent zooming. When showing an unlock symbol in snapping mode, tap it to allow rotation and zooming, but still prevent panning away from your current location.'),
//overflowMode: OverflowMode.extendBackground,
backgroundColor: Theme.of(context).primaryColor,
targetColor: Colors.white,
textColor: Colors.white,
child: CircularButton(
icon: Icon(rotateMapToUser ? Icons.lock_open : Icons.lock),
onPressed: () {
setState(() {
rotateMapToUser = !rotateMapToUser;
if (!rotateMapToUser) {
controller.rotate(0);
}
});
},
),
),
),
),
FloatingSearchBarAction(
showIfOpened: false,
child: Visibility(
visible: !moveMapToUser,
child: CircularButton(
icon: Icon(Icons.north),
onPressed: () {
setState(() {
controller.rotate(0);
});
},
),
),
),
FloatingSearchBarAction(
showIfOpened: false,
child: Visibility(
visible: !offlineMode,
child: DescribedFeatureOverlay(
featureId: 'refresh',
tapTarget: Icon(Icons.refresh),
title: Text('Refresh'),
description: Text(
'Tap this button to search the area visible on your device for GeoTags after panning the map.'),
//overflowMode: OverflowMode.extendBackground,
backgroundColor: Theme.of(context).primaryColor,
targetColor: Colors.white,
textColor: Colors.white,
child: CircularButton(
icon: const Icon(Icons.refresh),
onPressed: () {
//setState(() {
paintGeoTags(
true,
() => setState(() {
loadingSearch = true;
}),
() => setState(() {
loadingSearch = false;
}));
//});
}),
),
),
),
FloatingSearchBarAction( //Profile Pic icon
showIfOpened: !compassExpanded, //Don't worry about compassExpanded
child: Visibility(
visible: !offlineMode, //Should update on setState
child: DescribedFeatureOverlay(
featureId: 'profile',
tapTarget: Icon(Icons.account_circle),
title: Text('Public Profile'),
description: Text(
'Tap this button to view your public profile, and view information such as rank, total points and various other information. You can manage your profile by tapping the settings cog icon in that screen, or by choosing Manage My Profile from the menu. The colored border represents the color of your current rank, and the point will always face north. You can hold down on this icon to toggle the visibility of the compass point and to expand or reduce the height of the search bar. \n\nAfter you\'ve tapped the icon above to move to the next button introduction, tap the menu button in the top left, and your introduction will continue there!'),
overflowMode: OverflowMode.extendBackground,
backgroundColor: Theme.of(context).primaryColor,
targetColor: Colors.white,
textColor: Colors.white,
child: Hero(
tag: 'profileImage',
child: GestureDetector(
onTap: () => Navigator.pushNamed(
context,
ProfileScreen.routeName,
arguments: ScreenArguments(
globals.userData.displayName,
//'test user',
FirebaseFirestore.instance
.doc('users/' + globals.userData.uid),
true,
),
),
onLongPressStart: (e) {
setState(() {
compassExpanding = true;
});
},
onLongPressEnd: (e) => {
setState(() {
compassExpanded = !compassExpanded;
compassExpanding = false;
}),
//showLogoutAlert(context)
},
child: StreamBuilder<Object>(
stream: FlutterCompass.events,
builder: (context, compassDir) {
if (snapshot.hasError) {
return Center(
child: Text('Error: ${snapshot.error}'));
} else {
if (snapshot.data == null) {
return Container();
}
}
return Padding(
padding: const EdgeInsets.only(
left: 4,
),
child: Container(
width: 41,
height: 41,
transform: Matrix4Transform()
.rotateDegrees(
double.parse(((compassDir.data) ?? 0)
.toString()) *
-1 +
45,
origin: Offset(41 / 2, 41 / 2))
.matrix4,
decoration: ShapeDecoration(
//shape: BoxShape.circle,
shape: CustomRoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(21),
bottomRight: Radius.circular(21),
topRight: Radius.circular(21),
topLeft: Radius.circular(
compassExpanded ? 0 : 21),
),
leftSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
bottomLeftCornerSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
rightSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
bottomRightCornerSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
bottomSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
topSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
topRightCornerSide: BorderSide(
width: 2,
color: changeMedalColor(
snapshot.data.points),
),
),
color: //!compassExpanding
/*?*/ changeMedalColor(
snapshot.data.points)
//: Theme.of(context).accentColor,
/*border: Border.all(
width: 2,
color: changeMedalColor(snapshot.data.points),
),*/
),
//duration: Duration(milliseconds: 250),
child: SizedBox(
child: !compassExpanding
? Transform.rotate(
angle: vmath.radians(double.parse(
((compassDir.data) ?? 0)
.toString()) -
45),
child: CircleAvatar(
minRadius: 1000,
maxRadius: 5000,
backgroundImage: NetworkImage(
globals.userData.photoURL,
),
backgroundColor: changeMedalColor(
snapshot.data.points),
),
)
: Transform.rotate(
angle: vmath.radians(double.parse(
((compassDir.data) ?? 0)
.toString()) -
45),
child: Icon(Icons.expand,
color: Colors.white),
),
),
),
);
}),
),
),
),
),
),
],
builder: (context, transition) {
return ClipRRect(
//borderRadius: BorderRadius.circular(8),
child: Material(
color: Colors.white,
//elevation: 4.0,
child: !offlineMode
? Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Search for a GeoTag by name, approximate location. To search by author, use \'#\' in front of the search query.',
textAlign: TextAlign.center,
),
),
SizedBox(height: 15),
Column(
mainAxisSize: MainAxisSize.min,
children: Colors.accents.map((color) {
return Container(height: 112, color: color);
}).toList(),
),
],
)
: Column(
children: [
Center(
child: Icon(
Icons.cloud_off,
size: 40,
),
),
SizedBox(height: 10),
Text(
'You\'re in Offline Mode',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Text(
'Whilst in Offline Mode, the search feature is disabled.'),
],
),
),
);
},
),
);
}
Code inside drawer to update variable:
DescribedFeatureOverlay(
featureId: 'offlineMode',
tapTarget: Icon(Icons.file_download),
title: Text('Offline Mode'),
description: Text(
'One of the most important and complex features of this app. Allows for fully offline functioning, including downloading large areas of maps. You can see more detail about it\'s features and drawbacks by tapping this menu item after the introduction is complete.'),
overflowMode: OverflowMode.extendBackground,
backgroundColor: Theme.of(widget.mainContext).primaryColor,
targetColor: Colors.white,
textColor: Colors.white,
child: ListTile(
title: Text(offlineMode
? 'Offline Manager'
: (internetConnected
? 'Enable Offline Mode'
: 'Offline Mode Disabled')),
onTap: offlineMode
? () {
Navigator.pushNamed(
widget.mainContext, OfflineManagerScreen.routeName);
}
: (internetConnected //Don't worry about internetConnected
? () {
showAlert(
context,
widget.mainContext,
'Offline Mode',
<Widget>[
//Some text widgets
],
'Agree & Enable Offline Mode',
'Cancel', () {
StorageManager.saveData('offlineMode', 'true');
setState(() {
offlineMode = true; //Should Update
});
if (!Directory(globals.saveDir.path + '/tiles')
.existsSync()) {
Directory(globals.saveDir.path + '/tiles')
.createSync(recursive: true);
}
});
}
: null),
leading: Icon(offlineMode
? Icons.offline_pin
: (internetConnected
? Icons.file_download
: Icons.cloud_off)),
trailing: Switch(
value: offlineMode,
onChanged: offlineMode && internetConnected
? (bool newVal) {
showAlert(
context,
widget.mainContext,
'Disable Offline Mode',
<Widget>[
const Text(
'Disabling Offline Mode will delete all saved tiles, and resync information with the server. Any GeoTags tagged will be uploaded, and the appropriate point value will be added to your account. Are you sure you want to disable Offline Mode?',
textAlign: TextAlign.justify,
),
],
'Disable',
'Stay Offline', () {
setState(() {
offlineMode = false; //Should update
});
StorageManager.saveData('offlineMode', 'false');
Directory(globals.saveDir.path + '/tiles')
.deleteSync(recursive: true);
setState(() {
totalSize = 0;
filesList = [];
sizeList = [];
});
});
}
: null,
activeColor: Theme.of(widget.mainContext).primaryColorLight,
),
),
),
If you haven't already realised, this is my first big Flutter project, so tips about other things are also appreciated!
Widget is updating on inner widget. but all state is not being changed.
you should pass state to all your inner widgets like this (in showalert in your case)
StatefulBuilder(builder: (context, newState) {
return
showAlert(
context,
widget.mainContext,
'Offline Mode',
<Widget>[
//Some text widgets
],
'Agree & Enable Offline Mode',
'Cancel', () {
StorageManager.saveData('offlineMode', 'true');
newState(() {
offlineMode = true; //Should Update
});
if (!Directory(globals.saveDir.path + '/tiles')
.existsSync()) {
Directory(globals.saveDir.path + '/tiles')
.createSync(recursive: true);
}
});
});
Please try this! I didnt test, but the logic is you should pass the state.
Maybe you should wrap listtile with new state..

i have issue with design the ListTile in flutter

i an trying to design the add to cart button when user click on 'add to cart' the 'add to cart' button hides and ListTile appear that is on back of button and listtile have three things title , leading and trailing everything is works like i want but issue is i want the same size of list tile as button size so it won't grow when listtile appear on screen
here is the video to clear what i mean
https://youtu.be/Bq2mrc5ao94
here is my code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int total=0;
bool cartbuttoncheck=true;
bool listbool=false;
IconData delete_icon=Icons.remove;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Button"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Visibility(
visible: listbool,
child: Container(
color: Colors.green,
child: SizedBox(
height: 50.0,
width: 160.0,
child: ListTile(
title: Center(child: Text(total.toString(),style: TextStyle(fontStyle: FontStyle.italic,color: Colors.white),)),
leading: IconButton(
icon: Icon(delete_icon,color: Colors.white,),
onPressed: (){
setState(() {
if(total==2)
{
print("i am 2");
delete_icon=Icons.delete;
total--;
}
else if(total==1 && delete_icon==Icons.delete)
{
total=0;
listbool=false;
cartbuttoncheck=true;
}
if(total>2)
{
// delete_icon=Icons.remove;
total--;
}
});
},
),
trailing: IconButton(
icon: Icon(Icons.add,color: Colors.white),
onPressed: (){
setState(() {
if(total==1 && delete_icon==Icons.delete)
{
delete_icon=Icons.remove;
}
total++;
});
},
),
),
),
),
),
Stack(
alignment: Alignment.center,
children: <Widget>[
Visibility(
visible: cartbuttoncheck,
child: RaisedButton(
onPressed: (){
setState(() {
cartbuttoncheck=false;
listbool=true;
if(total==0)
{
total++;
delete_icon=Icons.delete;
}
});
},
child: Text("Add to Cart",style: TextStyle(color: Colors.white),),
color: Colors.green,
),
),
],
),
],
),
),
),
);
}
}
Just like the ListTile uses a SizedBox with a defined size you can do the same to the RaisedButton
SizedBox(
height: 50.0,
width: 160.0,
child: RaisedButton(
onPressed: (){
setState(() {
cartbuttoncheck=false;
listbool=true;
if(total==0){
total++;
delete_icon=Icons.delete;
}
});
},
child: Text("Add to Cart",style: TextStyle(color: Colors.white),),
color: Colors.green,
),
)
Having said that I believe it would be better to not use all of the widgets you use(Column, Stack, Visibility) and just change between the ListTile and the RaisedButton based on a bool value (listbool for example)
class _MyAppState extends State<MyApp> {
int total = 0;
bool listbool = false;
IconData delete_icon = Icons.remove;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Button"),
),
body: Center(
child: Container(
color: Colors.green,
height: 50.0,
width: 160.0,
child: listbool
? ListTile(
title: Center(
child: Text(
total.toString(),
style: TextStyle(
fontStyle: FontStyle.italic, color: Colors.white),
)),
leading: IconButton(
icon: Icon(
delete_icon,
color: Colors.white,
),
onPressed: () {
setState(() {
if (total == 2) {
print("i am 2");
delete_icon = Icons.delete;
total--;
} else if (total == 1 &&
delete_icon == Icons.delete) {
total = 0;
listbool = false;
}
if (total > 2) {
// delete_icon=Icons.remove;
total--;
}
});
},
),
trailing: IconButton(
icon: Icon(Icons.add, color: Colors.white),
onPressed: () {
setState(() {
if (total == 1 && delete_icon == Icons.delete) {
delete_icon = Icons.remove;
}
total++;
});
},
),
)
: RaisedButton(
onPressed: () {
setState(() {
listbool = true;
if (total == 0) {
total++;
delete_icon = Icons.delete;
}
});
},
child: Text(
"Add to Cart",
style: TextStyle(color: Colors.white),
),
color: Colors.green,
),
),
),
),
);
}
}
Now you have a container of a specific size of color green in the center and based on the value of the listbool it changes its child to the ListTile and RaisedButton
UPDATE
class _MyAppState extends State<MyApp> {
double width; //the width of the RaisedButton based on the text
double height; //the heightof the RaisedButton based on the text
EdgeInsets myPadding = EdgeInsets.all(8); //a known padding to use in the RaisedButton
#override
void initState(){
super.initState();
TextSpan longestParagraphTest = TextSpan(
text: "Add to Cart",
style: TextStyle(color: Colors.white, fontSize: 14),
);
TextPainter _textPainter = TextPainter(text: longestParagraphTest, textDirection: TextDirection.ltr, maxLines: 1)..layout(minWidth: 0.0, maxWidth: double.infinity);
width = _textPainter.width + 16; //this is the padding
height = _textPainter.height + 16; //this is the padding
}
int total = 0;
bool listbool = false;
IconData delete_icon = Icons.remove;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Button"),
),
body: Center(
child: Container(
duration: const Duration(milliseconds: 300),
color: Colors.green,
height: height,
width: width, //now you know the size of the RaisedButton and use it in both the ListTile and RaisedButton
child: listbool
? ListTile(
title: Center(
child: Text(
total.toString(),
style: TextStyle(
fontStyle: FontStyle.italic, color: Colors.white),
)),
leading: IconButton(
icon: Icon(
delete_icon,
color: Colors.white,
),
onPressed: () {
setState(() {
if (total == 2) {
print("i am 2");
delete_icon = Icons.delete;
total--;
} else if (total == 1 &&
delete_icon == Icons.delete) {
total = 0;
listbool = false;
}
if (total > 2) {
// delete_icon=Icons.remove;
total--;
}
});
},
),
trailing: IconButton(
icon: Icon(Icons.add, color: Colors.white),
onPressed: () {
setState(() {
if (total == 1 && delete_icon == Icons.delete) {
delete_icon = Icons.remove;
}
total++;
});
},
),
)
: RaisedButton(
padding: myPadding,
onPressed: () {
setState(() {
listbool = true;
if (total == 0) {
total++;
delete_icon = Icons.delete;
}
});
},
child: Text(
"Add to Cart",
maxLines: 1,
style: TextStyle(color: Colors.white, fontSize: 14),
),
color: Colors.green,
),
),
),
),
);
}
}
And you will get something like this because the button size is too small for a ListTile to show 2 icons and a text
I have 2 recommendations if you want to keep it this way, in the initState change the minWidth in layout(minWidth: 0.0, maxWidth: double.infinity); to a greater value (let's say 100.0) just to be sure in case your minWidth is too small it changes to 100 to fit the ListTile. My second recommendation is to use an AnimatedContainer and change the size based on the widget displayed
AnimatedContainer(
duration: const Duration(milliseconds: 300),
color: Colors.green,
height: listbool ? 50.0 : height, //it animates to a a better size to fit the listTile
width: listbool ? 200.0 : width, //it animates to a a better size to fit the listTile
child: listbool ? ListTile(...) : RaisedButton(...),
),
where height and width are the values calculated in the initState. It will do a smooth animation between the 2 sizes (just like your video but smoother and cleaner)

Flutter A RenderFlex overflowed by 99469 pixels on the bottom

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....');
}
},
),

If Else condition problem in onPressed() property in Dart/Flutter

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.