Flutter animated container change size of child widget - flutter

I'm trying to create a container in which I can perform two gesture: onTapDown and onTapUp. I want to decrease the dimension of my container when I perform onTapDown.
What I want is something like that:
https://i.imgur.com/7hW2Cn1.gifv
The problem is that if I work with AnimatedController I need to resize also the children and it's a mess.
I also looked to the flutter_bounce library but what I want is not something based on a duration. If the user keep pressed the container maintains the state of pressed.
class CustomContainerState extends State<CustomContainer> {
double width = 90.w;
double height = 35.h;
#override
Widget build(BuildContext context) {
return GestureDetector(
child: Center(
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
margin: EdgeInsets.only(left: 5.w, right: 5.w),
width: width,
height: height,
child: Column(
children: [
Container(
width: 90.w,
height: 25.h,
decoration: BoxDecoration(
color: green400,
borderRadius: BorderRadius.only(topLeft: Radius.circular(5.w), topRight: Radius.circular(5.w)),
),
),
Container(
margin: EdgeInsets.only(left: 5.w, right: 5.w, top: 1.h, bottom: 1.h),
width: 90.w,
height: 8.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(5.w), bottomRight: Radius.circular(5.w)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
"Ratings",
style: TextStyle(
fontFamily: "SanFrancisco",
fontSize: 10.sp,
fontWeight: FontWeight.w400,
overflow: TextOverflow.ellipsis,
),
),
Text(
"Title",
style: TextStyle(
fontFamily: "SanFrancisco",
fontSize: 12.sp,
fontWeight: FontWeight.w600,
overflow: TextOverflow.ellipsis,
),
),
Text(
"Description",
style: TextStyle(
fontFamily: "SanFrancisco",
fontSize: 10.sp,
fontWeight: FontWeight.w400,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
],
),
),
),
onTapDown: (tapDownDetails) {
setState(() {
width = 85.w;
height = 30.h;
});
},
onTapUp: (TapUpDetails) {
setState(() {
width = 90.w;
height = 35.h;
});
},
);
}
}
The problem so is how to decrease only the parent container that automatically decrease also the children? Because I can use multiple AnimatedContainer also for the children but the problem is that the text is not animated.

Have you tried with scale instead of changing width and height? Something like this:
class CustomContainerState extends State<CustomContainer> {
double width = 90;
double height = 350;
double scale = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: GestureDetector(
child: Center(
child: AnimatedContainer(
transform: Matrix4.identity()..scale(scale),
color: Colors.green,
duration: Duration(milliseconds: 200),
margin: EdgeInsets.only(left: 5, right: 5),
width: width,
height: height,
child: Column(
children: [
Container(
width: 90,
height: 25,
decoration: BoxDecoration(
// color: green400,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5),
topRight: Radius.circular(5)),
),
),
Container(
margin: EdgeInsets.only(
left: 5, right: 5, top: 1, bottom: 1),
width: 90,
height: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5),
bottomRight: Radius.circular(5)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
"Ratings",
style: TextStyle(
fontFamily: "SanFrancisco",
fontSize: 10,
fontWeight: FontWeight.w400,
overflow: TextOverflow.ellipsis,
),
),
Text(
"Title",
style: TextStyle(
fontFamily: "SanFrancisco",
fontSize: 12,
fontWeight: FontWeight.w600,
overflow: TextOverflow.ellipsis,
),
),
Text(
"Description",
style: TextStyle(
fontFamily: "SanFrancisco",
fontSize: 10,
fontWeight: FontWeight.w400,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
],
),
),
),
onTapDown: (tapDownDetails) {
setState(() {
// width = 85;
// height = 300;
scale = .8;
});
},
onTapUp: (TapUpDetails) {
setState(() {
// width = 90;
// height = 350;
scale = 1;
});
},
),
),
);
}
}

Related

NavigationBar is imported from both 'package:flutter/src/material/navigation_bar.dart' and 'package:flutter_onboarding_slider/navigation_bar.dart'

**i am facing error while running error is this because of packges or something else i have remove all the old code and add new still facing following error.
Error: 'NavigationBar' is imported from both 'package:flutter/src/material/navigation_bar.dart' and 'package:flutter_onboarding_slider/navigation_bar.dart'.
appBar: NavigationBar(
^^^^^^^^^^^^^
: Warning: Operand of null-aware operation '?.' has type 'GoogleMapController' which excludes null.
lib/…/map/map.dart:62
'GoogleMapController' is from 'package:google_maps_flutter/google_maps_flutter.dart' ('/D:/flutter/.pub-cache/hosted/pub.dartlang.org/google_maps_flutter-2.1.7/lib/google_maps_flutter.dart').
package:google_maps_flutter/google_maps_flutter.dart:1
_controller?.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
^
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_onboarding_slider/flutter_onboarding_slider.dart';
import 'package:fyppedometer/mainScreens/Navigation/navigationBar.dart';
import 'package:fyppedometer/widgets/constants.dart';
import 'package:fyppedometer/widgets/text.dart';
class MyHome extends StatefulWidget {
const MyHome({Key? key}) : super(key: key);
#override
State<MyHome> createState() => _MyHomeState();
}
class _MyHomeState extends State {
final Color kDarkBlueColor = Colors.cyan;
// ignore: non_constant_identifier_names
List<String> numbers_Height = [
for (var i = 1.1; i <= 10.0; i = i + 0.1) i.toString()
];
// ignore: non_constant_identifier_names
List<String> numbers_Weight = [for (var i = 1; i <= 1000; i++) i.toString()];
int _groupValue = -1;
String _selectedGender = 'male';
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
// color: Colors.amber,
child: OnBoardingSlider(
buttonText: 'Start',
onFinish: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => Navbar(),
),
);
},
buttonTextColor: Colors.cyan,
// skipTextButton: Text(
// 'Skip',
// style: TextStyle(
// fontSize: 16,
// color: kDarkBlueColor,
// fontWeight: FontWeight.w600,
// ),
// ),
// trailing: Text(
// 'Login',
// style: TextStyle(
// fontSize: 16,
// color: kDarkBlueColor,
// fontWeight: FontWeight.w600,
// ),
// ),
// trailingFunction: () {
// // Navigator.push(
// // context,
// // CupertinoPageRoute(
// // builder: (context) => LoginPage(),
// // ),
// // );
// },
controllerColor: kDarkBlueColor,
totalPage: 3,
headerBackgroundColor: liteblue,
pageBackgroundColor: liteblue,
background: [
Padding(
padding: const EdgeInsets.only(top: 210, left: 80),
child: Image.asset(
'assets/gender.png',
height: MediaQuery.of(context).size.height * 0.6,
width: MediaQuery.of(context).size.width * 0.6,
),
),
Padding(
padding: const EdgeInsets.only(top: 160, left: 60),
child: Image.asset(
'assets/walking.png',
height: MediaQuery.of(context).size.height * 0.7,
width: MediaQuery.of(context).size.width * 0.7,
),
),
Padding(
padding: const EdgeInsets.only(top: 200, left: 60),
child: Image.asset(
'assets/human.png',
height: MediaQuery.of(context).size.height * 0.6,
width: MediaQuery.of(context).size.width * 0.6,
),
),
],
speed: 1.8,
pageBodies: [
Container(
// padding: EdgeInsets.symmetric(horizontal: 40),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
'What’s Your Gender',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
const Text(
'Calories & Stride length calculation need it ',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white60,
fontSize: 21.0,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: size.height * 0.1,
width: size.width * 0.5,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(25), // radius of 10
color: Color.fromARGB(255, 19, 65, 103),
),
child: Center(
child: ListTile(
leading: Radio<String>(
activeColor: Colors.white,
value: 'male',
groupValue: _selectedGender,
onChanged: (value) {
setState(() {
_selectedGender = value!;
});
},
),
title: text(
textData: "Male",
color: Colors.white,
fontsize: 20.0,
fontweight: FontWeight.bold),
// Text(_selectedGender == 'male' ? 'Hello gentlement!' : 'Hi lady!')
),
),
),
SizedBox(height: 20),
Container(
height: size.height * 0.1,
width: size.width * 0.5,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(25), // radius of 10
color: Color.fromARGB(255, 19, 65, 103),
),
child: Center(
child: ListTile(
leading: Radio<String>(
activeColor: Colors.white,
value: 'female',
groupValue: _selectedGender,
onChanged: (value) {
setState(() {
_selectedGender = value!;
});
},
),
title: text(
textData: "Female",
color: Colors.white,
fontsize: 20.0,
fontweight: FontWeight.bold),
// Text(_selectedGender == 'male' ? 'Hello gentlement!' : 'Hi lady!')
),
),
),
],
)
]),
),
Container(
// padding: EdgeInsets.symmetric(horizontal: 40),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
'How Tall are you?',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 28.0,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
const Text(
'To Personalize Your Fitness Goal ',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white60,
fontSize: 20.0,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
height: size.height * 0.10,
width: size.width * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: Color.fromARGB(255, 145, 174, 225))),
child: Center(
child: text(
textData: "Height",
fontsize: 30.0,
fontweight: FontWeight.bold,
color: Color.fromARGB(255, 147, 148, 152)),
),
),
),
SizedBox(
height: 30,
),
Center(
child: Container(
height: size.height * 0.13,
width: size.width * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Color.fromARGB(255, 92, 89, 89)),
// color: Colors.white,
),
child: ListWheelScrollView.useDelegate(
itemExtent: 100,
// controller: fixedExtentScrollController,
physics: FixedExtentScrollPhysics(),
onSelectedItemChanged: (i) {
print(numbers_Height[i]);
},
childDelegate: ListWheelChildLoopingListDelegate(
children: <Widget>[
...numbers_Height.map((String number) {
return Center(
child: Text(
number,
style: const TextStyle(
fontSize: 28.0,
color: Colors.white,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.normal,
decoration: TextDecoration.none),
),
);
})
],
),
),
),
)
],
)
]),
),
Container(
// padding: EdgeInsets.symmetric(horizontal: 40),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
'How much do you Weight?',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 28.0,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
const Text(
'To Personalize Your Fitness Goal ',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white60,
fontSize: 20.0,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
height: size.height * 0.10,
width: size.width * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: Color.fromARGB(255, 145, 174, 225))),
child: Center(
child: text(
textData: "Weight",
fontsize: 30.0,
fontweight: FontWeight.bold,
color: Color.fromARGB(255, 147, 148, 152)),
),
),
),
SizedBox(
height: 30,
),
Center(
child: Container(
height: size.height * 0.13,
width: size.width * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Color.fromARGB(255, 92, 89, 89)),
),
child: ListWheelScrollView.useDelegate(
itemExtent: 100,
physics: FixedExtentScrollPhysics(),
onSelectedItemChanged: (i) {
print(numbers_Weight[i]);
},
childDelegate: ListWheelChildLoopingListDelegate(
children: <Widget>[
...numbers_Weight.map((String number) {
return Center(
child: Text(
number, //Here is the child value I would like to get
style: const TextStyle(
fontSize: 28.0,
color: Colors.white,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.normal,
decoration: TextDecoration.none),
),
);
})
],
),
),
),
)
],
)
]),
),
],
),
);
}
}
Use show and hide to import part of a library.
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
See Using libraries for details.

Column widget not positioning widgets properly when using Stack widget-Flutter

The first image is the design of the app from Figma. While the next image is the one which I am getting though I am using simple stack and columns. I am not being able to understand why it is coming out as such. The Text Widgets must be under the picture but they are going right at the bottom of the screen. Can anyone help me out with this one?
My code:
import 'package:flutter/material.dart';
import '../../app_theme.dart';
class ProfileScreen extends StatefulWidget {
const ProfileScreen({Key? key}) : super(key: key);
#override
_ProfileScreenState createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: AppTheme.lightBlue,
title: Text(
'Profile',
style: TextStyle(color: AppTheme.black100),
),
elevation: 0,
),
body: Column(
children: [
SizedBox(
height: 50,
),
Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Container(
width: double.infinity,
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(16),
topLeft: Radius.circular(16),
),
color: AppTheme.lightGrey),
),
Positioned(
top: -50,
child: _buildProfileDetails(),
),
],
)
],
),
backgroundColor: AppTheme.lightBlue,
drawer: Drawer(),
);
}
Widget _buildProfileDetails() {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
clipBehavior: Clip.none,
children: [
CircleAvatar(
radius: 50,
backgroundImage: AssetImage('assets/images/profile_photo.jpg'),
),
Positioned(
left: 78,
top: 60,
child: CircleAvatar(
radius: 14,
backgroundColor: AppTheme.blue,
child: Icon(Icons.camera_alt_outlined),
),
),
],
),
Text(
'Alexis Sanchez',
style: TextStyle(
color: AppTheme.black100,
fontSize: 22,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins',
height: 33,
),
textAlign: TextAlign.center,
),
Text(
'Alexis Sanchez',
style: TextStyle(
color: AppTheme.black80,
fontSize: 12,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins',
height: 18,
),
textAlign: TextAlign.center,
),
Text(
'Alexis Sanchez',
style: TextStyle(
color: AppTheme.black80,
fontSize: 12,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins',
height: 18,
),
textAlign: TextAlign.center,
),
],
);
}
}
Stack widget extends and fills all the available space. if you want your stack to be smaller than all available space. wrap it inside a SizedBox widget.
If you need to control height, do like height: 1.2. and use mainAxisSize: MainAxisSize.min, on Column.
I am using different approach to gain this and will contain some extra widget for future purpose. Mostly describe on code-comment. If you face any issue while scaling/increasing size, adjust the parent Container size. Used demo color for design purpose.
Run on dartPad.
Result will be:
body: LayoutBuilder(
builder: (context, constraints) {
return Column(
children: [
/// header Part: Name, logo, info
Container(
color: Colors.grey,
height: kToolbarHeight * 3, //adjust box Stack size
child: Stack(
children: [
/// bottom Half background
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: kToolbarHeight * 2,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(16),
topLeft: Radius.circular(16),
),
),
),
),
/// center logo with info
Positioned(
bottom: 10,
left: 0,
right: 0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 50 * 2, // from your logo radius
width: 50 * 2 +
7, //7 is from `camera_alt_outlined` to align
child: Stack(
children: const [
CircleAvatar(
radius: 50,
backgroundColor: Colors.deepPurple,
// backgroundImage: AssetImage(
// 'assets/images/profile_photo.jpg'),
),
Positioned(
bottom: 7,
right: 0,
child: CircleAvatar(
radius: 14,
backgroundColor: Colors.blue,
child: Icon(Icons.camera_alt_outlined),
),
)
],
),
),
///now rest of Text
const Text(
'Alexis Sanchez',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins',
height: 1.2),
textAlign: TextAlign.center,
),
const Text(
'Alexis Sanchez',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins',
),
textAlign: TextAlign.center,
),
const Text(
'Alexis Sanchez',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins',
),
textAlign: TextAlign.center,
),
],
),
),
],
),
)
],
);
},
));
I would have put child in this container and put everything that I want on this background
Must use screenutil helps for different screen sizes
Container(
width: double.infinity,
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(16.sp),
topLeft: Radius.circular(16.sp),
),
color: AppTheme.lightGrey),
),

Flutter Card Layout

So I'm new to flutter, and I'm trying to make a card. But I can't seem to get my desired output.
I tried to separate the different widgets, by using rows and columns, but I kept messing it up.
This is my target output
Target output
This is my current progressCurrent progress
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildhomePageAppBar(),
body: buildExhibitorBody(),
);
}
Widget buildExhibitorBody() {
return Container(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
buildExhibitorText(),
SizedBox(
height: 10,
),
buildExhibitorCards(),
SizedBox(height: 10),
],
),
),
);
}
Widget buildhomePageAppBar() {
double profileDimension = 35;
return AppBar(
backgroundColor: Colors.white,
titleSpacing: 0,
title: Padding(
padding: EdgeInsets.only(
left: 20,
),
child: Row(
children: [
Padding(
padding: EdgeInsets.only(
top: 5,
bottom: 5,
),
child: Image(
image: AssetImage('assets/images/plain_logo.png'),
height: 30,
),
),
SizedBox(width: 5),
Text(
'Virtex',
style: TextStyle(
color: Colors.black87,
fontFamily: 'Poppins',
fontSize: 16,
fontWeight: FontWeight.bold,
),
)
],
),
),
actions: [
Padding(
padding: EdgeInsets.only(
top: 10,
bottom: 10,
),
child: Container(
height: profileDimension,
width: profileDimension,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.black54,
width: 2,
),
borderRadius: BorderRadius.circular(50),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image(
width: profileDimension,
height: profileDimension,
image: AssetImage(
'assets/images/profile-image.jpeg',
),
fit: BoxFit.cover,
),
),
),
),
SizedBox(width: 20),
],
);
}
Widget buildExhibitorText() {
return Padding(
padding: EdgeInsets.only(
left: 20,
right: 20,
top: 20,
bottom: 10,
),
child: Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(
"Exhibitors",
textAlign: TextAlign.justify,
style: TextStyle(
fontFamily: "DMSans",
letterSpacing: -0.2,
fontSize: 20.0,
color: Colors.black,
fontWeight: FontWeight.w400,
),
),
),
],
),
),
);
}
Widget buildExhibitorCards() { // I think my problem is I don't know how to do the layout here
return Container(
width: 400,
height: 150,
child: Column(children: <Widget>[
Card(
elevation: 1,
child: Padding(
padding: const EdgeInsets.only(),
child: Row(children: [
buildCardImage(),
buildCardExhibitor(),
buildCardIndustry(),
buildCardGo(),
])),
),
]),
);
}
Widget buildCardExhibitor() {
return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
padding: EdgeInsets.all(10),
width: 40,
height: 40,
child: Center(
child: Row(
children: <Widget>[
Text(
"EN",
style: TextStyle(
fontSize: 15.0,
color: Colors.white,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
Text('Exhibitor Name')
],
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(200),
),
color: Colors.red,
),
),
]);
}
Widget buildCardImage() {
return Container(
height: 100,
width: 100,
child: Image(
image: AssetImage('assets/images/onboarding-2.jpg'),
height: 100,
),
);
}
Widget buildCardIndustry() {
return Padding(
padding: EdgeInsets.only(
left: 40,
right: 40,
),
child: Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
"Industry 1",
style: TextStyle(
fontFamily: "DMSans",
color: Colors.grey,
letterSpacing: 0.3,
fontSize: 12,
),
),
Text(
"Industry 2",
style: TextStyle(
fontFamily: "DMSans",
letterSpacing: -0.3,
fontSize: 12,
color: Colors.grey,
fontWeight: FontWeight.w500,
),
),
],
),
),
);
}
Widget buildCardGo() {
return Row(mainAxisAlignment: MainAxisAlignment.end, children: [
Text(
'Go to Booth',
style: TextStyle(
color: Colors.blue,
fontFamily: 'Poppins',
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
SizedBox(width: 5),
IconButton(
icon: Icon(
MdiIcons.fromString('arrow-right'),
size: 30,
color: Colors.black,
),
onPressed: () {
Navigator.of(context).pop();
},
),
]);
}
}
I would greatly appreciate any kind of help.
Look:
My own Code
import 'package:flutter/material.dart';
class CardLayout extends StatelessWidget {
Widget buildCardImage = Container(
margin: EdgeInsets.only(right: 10.0),
width: 150,
height: 150,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage("https://picsum.photos/250?image=9"),
),
),
);
Widget buildCardExhibitor =
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
Container(
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(200),
),
color: Colors.red,
),
child: Text(
"EN",
style: TextStyle(
fontSize: 15.0,
color: Colors.white,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
SizedBox(
width: 10.0,
),
Text(
'Exhibitor Name',
style: TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
]);
Widget buildCardIndustry = Padding(
padding: EdgeInsets.all(8.0),
child: Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding:
EdgeInsets.only(left: 10.0, right: 10.0, top: 5, bottom: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(100),
),
color: Colors.blueGrey.shade400,
),
child: Text(
'Industry 1',
style: TextStyle(
fontFamily: "DMSans",
color: Colors.white,
letterSpacing: 0.3,
fontSize: 12,
),
),
),
SizedBox(
width: 10.0,
),
Container(
padding:
EdgeInsets.only(left: 10.0, right: 10.0, top: 5, bottom: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(100),
),
color: Colors.blueGrey.shade400,
),
child: Text(
'Industry 2',
style: TextStyle(
fontFamily: "DMSans",
color: Colors.white,
letterSpacing: 0.3,
fontSize: 12,
),
),
),
],
),
),
);
Widget buildCardGo = Row(mainAxisAlignment: MainAxisAlignment.end, children: [
Text(
'Go to Booth',
style: TextStyle(
color: Colors.blue,
fontFamily: 'Poppins',
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
SizedBox(width: 3),
IconButton(
icon: Icon(
Icons.arrow_forward_rounded,
size: 30,
color: Colors.blue,
),
onPressed: () {
//Navigator.pop(context);
},
),
]);
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Exhibitor'),
actions: [
IconButton(
icon: Icon(Icons.filter_list_rounded),
onPressed: () {
Navigator.pop(context);
})
],
),
body: Container(
margin: EdgeInsets.only(top: 10.0),
width: MediaQuery.of(context).size.width,
//height: 150.0, // remove this line -------------- (1) [EDIT]
child: Column(
// wrap card with column and add listtile as children -------------- (2) [EDIT]
children: [
ListTile(
leading: Text('Exhibitor'),
trailing: IconButton(
icon: Icon(Icons.filter_list_rounded),
onPressed: () {
Navigator.pop(context);
}),
),
Card(
elevation: 5.0,
color: Colors.white,
child: Padding(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
buildCardImage,
Expanded(
child: Column(
children: <Widget>[
buildCardExhibitor,
buildCardIndustry,
buildCardGo
],
))
],
),
),
),
],
),
),
));
}
}

Error updating UI, setState() not working in flutter

I have two buttons on flutter screen (add to cart and remove from cart).
cartQuantity is a variable I have declared in my build() method to keep a track of users cart quantity.
When the user presses the add button, the UI for quantity x rate should change which doesn't seem to happen.
The Row widget contains 'REMOVE' button, user's cart quantity and 'ADD' button respectively.
class ItemBottomSheet extends StatefulWidget {
final RestaurantItems restaurantItem;
final Restaurant restaurant;
const ItemBottomSheet({
this.restaurantItem,
this.restaurant,
});
#override
_ItemBottomSheetState createState() => _ItemBottomSheetState();
}
class _ItemBottomSheetState extends State<ItemBottomSheet> {
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final cartItems = Provider.of<Cart>(context).getCartItems;
final index = cartItems.indexWhere((cartItem) =>
cartItem.id == widget.restaurantItem.id &&
cartItem.restaurantId == widget.restaurant.id);
int restQuantity = widget.restaurantItem.quantity;
int cartQuantity = 0;
if (index != -1) {
cartQuantity = cartItems[index].quantity;
}
return Container(
decoration: new BoxDecoration(
color: darkThemeColour,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(20.0),
topRight: const Radius.circular(20.0))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: new BoxDecoration(
color: Colors.transparent,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(20.0),
topRight: const Radius.circular(20.0))),
height: size.height * 0.21,
width: double.infinity,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
child: Image.network(
widget.restaurantItem.imageUrl,
fit: BoxFit.cover,
),
),
),
Row(
// crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// SizedBox(
// height: 12,
// width: 12,
// child: SvgPicture.asset(
// 'lib/assets/icons/green-circle.svg',
// color: restaurantItem.isVeg ? Colors.green : Colors.red,
// ),
// ),
Padding(
padding: const EdgeInsets.only(top: 25, left: 18),
child: Text(
widget.restaurantItem.name,
style: TextStyle(
color: Colors.white,
fontFamily: 'Raleway',
fontSize: 21,
fontWeight: FontWeight.w600),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 17),
child: Text(
'₹${widget.restaurantItem.price}',
style: TextStyle(
color: Colors.green,
fontFamily: 'Raleway',
fontSize: 18,
fontWeight: FontWeight.w900),
),
),
Padding(
padding: const EdgeInsets.only(top: 27),
child: Text(
'Pickup Between',
style: TextStyle(
color: Colors.white,
fontFamily: 'Raleway',
fontSize: 14,
fontWeight: FontWeight.w300),
),
),
Padding(
padding: const EdgeInsets.only(top: 15),
child: Text(
'${DateFormat.jm().format(widget.restaurant.pickupTime.start)} - ${DateFormat.jm().format(widget.restaurant.pickupTime.end)}',
style: TextStyle(
color: Colors.white,
fontFamily: 'Raleway',
fontSize: 17,
fontWeight: FontWeight.w400),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.only(top: 25, left: 18),
child: ClipOval(
child: Material(
color: index == -1 ||
cartItems[index].quantity == 0 ||
widget.restaurantItem.quantity <= 1
? Colors.grey
: Colors.green, // button color
child: InkWell(
splashColor: Colors.white30, // inkwell color
child: SizedBox(
width: 60,
height: 60,
child: Icon(
Icons.remove,
color: Colors.white,
size: 28,
)),
onTap: () {},
),
),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Text(
cartQuantity > 0
? '$cartQuantity x ₹${widget.restaurantItem.price}'
: '₹${widget.restaurantItem.price}',
style: TextStyle(
color: Colors.white,
fontFamily: 'Raleway',
fontSize: 22,
fontWeight: FontWeight.w900),
),
),
Padding(
padding: const EdgeInsets.only(top: 25, right: 18),
child: ClipOval(
child: Material(
color: widget.restaurantItem.quantity <= 1
? Colors.grey
: Colors.green, // button color
child: InkWell(
splashColor: Colors.white30, // inkwell color
child: SizedBox(
width: 56,
height: 56,
child: Icon(
Icons.add,
color: Colors.white,
)),
onTap: () {
setState(() {
cartQuantity++;
print(cartQuantity.toString());
});
},
),
),
),
),
],
),
FillButton(
text: 'ADD TO CART',
function: () {
// setState(() {
// cartQuantity++;
// });
},
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text(
widget.restaurantItem.isVeg ? 'VEG' : 'NON - VEG',
style: TextStyle(
fontFamily: 'Raleway',
fontSize: 17,
fontWeight: FontWeight.w800,
color:
widget.restaurantItem.isVeg ? Colors.green : Colors.red),
),
),
Container(
height: size.height * 0.3,
color: darkThemeColour,
)
],
),
);
}
}
Your issue is because in your build you are initialiazing your cartQuantity to 0 each time you do a rebuild of the widget. You should initialize it outside the build.
class _ItemBottomSheetState extends State<ItemBottomSheet> {
int cartQuantity = 0;
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final cartItems = Provider.of<Cart>(context).getCartItems;
final index = cartItems.indexWhere((cartItem) =>
cartItem.id == widget.restaurantItem.id &&
cartItem.restaurantId == widget.restaurant.id);
int restQuantity = widget.restaurantItem.quantity;
Now your value will not be always 0 because you initialize it in the construction of the widget. Each time you call setState you do a rebuild and you build gets called.

Flutter showModalBottomSheet not changing state need to reopen it to see changes

I am showing showModalBottomSheet issue is its not changing the state I need t close the showModalBottomSheet and open it again to see the changes. Here is my code
List sort = [
{'CatID': 0, 'Name': 'Trending'},
{'CatID': 1, 'Name': 'Newest'},
{'CatID': 2, 'Name': 'Lowset Price'},
{'CatID': 3, 'Name': 'Highest Price'},
];
class BrowserCategoryPage2 extends StatefulWidget {
final subCategory;
const BrowserCategoryPage2({Key key, #required this.subCategory})
: super(key: key);
#override
_BrowserCategoryPage2State createState() => _BrowserCategoryPage2State();
}
class _BrowserCategoryPage2State extends State<BrowserCategoryPage2> {
var items = {'Items': []};
int dateindex;
bool showNotAvail = false;
#override
void initState() {
super.initState();
print('browse subcategory');
print(widget.subCategory);
widget.subCategory.forEach((subcategory) {
items['Items'].addAll(subcategory['Items']);
});
print(items);
print('sada');
}
int currentindex = 0;
int sortindex = 0;
#override
Widget build(BuildContext context) {
double Height = MediaQuery.of(context).size.height;
double Width = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SideInAnimation(
2,
child: Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 18.0, vertical: 18),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Products',
style: Theme.of(context).textTheme.headline3,
).tr(),
IconButton(
icon: Icon(
FlutterIcons.filter_fea,
color: Theme.of(context).primaryColor,
),
onPressed: () {
OpenFilter(context);
},
),
]),
),
),
),
SizedBox(height: 10.0),
],
),
),
),
);
}
OpenFilter(BuildContext context){
return showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
double Height = MediaQuery.of(context).size.height;
double Width = MediaQuery.of(context).size.width;
final SortWidget = <Widget>[]; // Here we defined a list of widget!
for (int i = 0; i < sort.length; i++) {
SortWidget.add(
GestureDetector(
onTap: () {
setState(() {
// set current index!
sortindex = i;
print(sortindex);
});
},
child: Container(
height: Height * 0.04,
width: Width * 0.2,
decoration: BoxDecoration(
color: sortindex == i ? Color(0xff04385f) : Colors.white,
border: Border.all(
color:
sortindex == i ? Color(0xff04385f) : Colors.grey[500]),
borderRadius: BorderRadius.all(Radius.circular(10))),
child: Center(
child: Text(
sort[i]['Name'],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 9,
color: sortindex == i ? Colors.white : Colors.grey[500],
fontFamily: 'UbuntuRegular'),
)),
),
),
);
}
return Container(
decoration: BoxDecoration(
borderRadius: new BorderRadius.only(
topLeft:
const Radius.circular(10.0),
topRight:
const Radius.circular(10.0))),
child: new Column(
children: [
Container(
width: double.infinity,
height: Height * 0.055,
decoration: BoxDecoration(
color: Color(0xfff7f7f7)),
child: Center(
child: RichText(
text: new TextSpan(
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(
text: 'Sort & ',
style: new TextStyle(
fontSize: 18,
fontFamily:
'UbuntuBold')),
new TextSpan(
text: 'Filter',
style: TextStyle(
fontSize: 18,
fontFamily:
'UbuntuMedium',
)),
],
),
),
),
),
SizedBox(
height: Height * 0.01,
),
Padding(
padding: const EdgeInsets.only(
left: 13, bottom: 13),
child: Align(
alignment: Alignment.centerLeft,
child: RichText(
text: new TextSpan(
// Note: Styles for TextSpans must be explicitly defined.
// Child text spans will inherit styles from parent
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(
text: 'Sort ',
style: new TextStyle(
fontSize: 16,
fontFamily:
'UbuntuBold')),
new TextSpan(
text: 'By',
style: TextStyle(
fontSize: 16,
fontFamily:
'UbuntuMedium',
)),
],
),
),
),
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: SortWidget,
),
Padding(
padding: const EdgeInsets.only(
left: 13, right: 13, top: 13),
child: Divider(
color: Colors.grey,
thickness: 1,
),
),
SizedBox(
height: Height * 0.01,
),
Padding(
padding: const EdgeInsets.only(
left: 10, right: 10, top: 20),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Container(
height: Height * 0.06,
width: Width * 0.57,
decoration: BoxDecoration(
color: Color(0xff04385f),
borderRadius:
BorderRadius.only(
topLeft:
Radius.circular(
12),
topRight:
Radius.circular(
12),
bottomLeft:
Radius.circular(
12),
bottomRight:
Radius.circular(
12)),
),
child: Center(
child: Text(
'Apply Filters',
style: TextStyle(
fontSize: 15,
fontWeight:
FontWeight.bold,
fontFamily:
'UbuntuRegular',
color: Colors.white),
)),
),
Container(
height: Height * 0.06,
width: Width * 0.3,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey),
color: Colors.white,
borderRadius:
BorderRadius.only(
topLeft:
Radius.circular(
12),
topRight:
Radius.circular(
12),
bottomLeft:
Radius.circular(
12),
bottomRight:
Radius.circular(
12)),
),
child: Center(
child: Text(
'Reset',
style: TextStyle(
fontSize: 15,
fontWeight:
FontWeight.bold,
fontFamily:
'UbuntuRegular',
color:
Color(0xff04385f)),
)),
),
],
),
)
],
),
);
});
}
}
You can see I simply change the color of the container on click. It's changing the index of sort index but issue is it's not changing the state. Mean if I close and open the bottom sheet then I can see the changes.
If flutter BottomSheet works as a widget, so bottomSheet has its own state which does not refresh the data when you call setState({}) of parent Class.
For that you need to use StatefulBuilder for refresh the content of bottomSheet like :
await showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return StatefulBuilder(builder: (BuildContext context, StateSetter state) {
return Container();
});
});
Please replace your method with the following solution it will work properly:
OpenFilter(BuildContext context) {
return showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
double Height = MediaQuery.of(context).size.height;
double Width = MediaQuery.of(context).size.width;
final SortWidget = <Widget>[]; // Here we defined a list of widget!
for (int i = 0; i < sort.length; i++) {
SortWidget.add(
GestureDetector(
onTap: () {
setState(() {
// set current index!
sortindex = i;
print(sortindex);
});
},
child: Container(
height: Height * 0.04,
width: Width * 0.2,
decoration: BoxDecoration(
color: sortindex == i ? Color(0xff04385f) : Colors.white,
border: Border.all(color: sortindex == i ? Color(0xff04385f) : Colors.grey[500]),
borderRadius: BorderRadius.all(Radius.circular(10))),
child: Center(
child: Text(
sort[i]['Name'],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 9,
color: sortindex == i ? Colors.white : Colors.grey[500],
fontFamily: 'UbuntuRegular'),
)),
),
),
);
}
return Container(
decoration: BoxDecoration(
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0), topRight: const Radius.circular(10.0))),
child: new Column(
children: [
Container(
width: double.infinity,
height: Height * 0.055,
decoration: BoxDecoration(color: Color(0xfff7f7f7)),
child: Center(
child: RichText(
text: new TextSpan(
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(text: 'Sort & ', style: new TextStyle(fontSize: 18, fontFamily: 'UbuntuBold')),
new TextSpan(
text: 'Filter',
style: TextStyle(
fontSize: 18,
fontFamily: 'UbuntuMedium',
)),
],
),
),
),
),
SizedBox(
height: Height * 0.01,
),
Padding(
padding: const EdgeInsets.only(left: 13, bottom: 13),
child: Align(
alignment: Alignment.centerLeft,
child: RichText(
text: new TextSpan(
// Note: Styles for TextSpans must be explicitly defined.
// Child text spans will inherit styles from parent
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(text: 'Sort ', style: new TextStyle(fontSize: 16, fontFamily: 'UbuntuBold')),
new TextSpan(
text: 'By',
style: TextStyle(
fontSize: 16,
fontFamily: 'UbuntuMedium',
)),
],
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: SortWidget,
),
Padding(
padding: const EdgeInsets.only(left: 13, right: 13, top: 13),
child: Divider(
color: Colors.grey,
thickness: 1,
),
),
SizedBox(
height: Height * 0.01,
),
Padding(
padding: const EdgeInsets.only(left: 10, right: 10, top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: Height * 0.06,
width: Width * 0.57,
decoration: BoxDecoration(
color: Color(0xff04385f),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12)),
),
child: Center(
child: Text(
'Apply Filters',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
fontFamily: 'UbuntuRegular',
color: Colors.white),
)),
),
Container(
height: Height * 0.06,
width: Width * 0.3,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft: Radius.circular(12),
bottomRight: Radius.circular(12)),
),
child: Center(
child: Text(
'Reset',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
fontFamily: 'UbuntuRegular',
color: Color(0xff04385f)),
)),
),
],
),
)
],
),
);
});
});
}
Flutter is amazing at rebuilding its widgets as little as possible. So if there are any constant widgets/values, it won't rebuild them. This also applies to bottom sheets.
If you would like to have your bottom sheet update with hot restart you can create a stateful widget within your bottomsheet and then it will update.
Here is an example of such:
class MyBottomSheet extends StatefulWidget {
const MyBottomSheet({
Key key,
}) : super(key: key);
Future<T> show<T>(BuildContext context) {
return showModalBottomSheet<T>(
context: context,
isDismissible: true,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (_) => return this,
);
}
#override
_MyBottomSheetState createState() => _MyBottomSheetState();
}
class _MyBottomSheetState extends State<MyBottomSheet> {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
height: 310,
);
}
}
and to access the bottom sheet you can call it via MyBottomSheet().show(context);
to see the changes made to your showModalBottomSheet with Hot Reload just extract the Widget from the return value.
Example:
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: (){
showModalBottomSheet(
context: context, builder: (context){
return AddNoteBottomSheet();
});
}, child: Text('+', style: TextStyle(fontSize: 30.0),),),
body: NotesViewBody(),
);
}
now you ca see all changes made on AddNoteBottomSheet() widget with hot reload reload.