Flutter: Expanded IconButton still shows under the Container - flutter

AnimatedContainer(
...
child: Container(
child: Column(
children: [
Row(
children: [
Container(
width:60,
height:50,
color: Colors.black,
),
],
),
Expanded(
child: GestureDetector(
onTap: () {
print('what');
},
child: Container(
height: 50,
child: Column(
children: [
Expanded(
child: Text('asdf'),
),
Expanded(
child: IconButton(
icon: Icon(Icons.ac_unit),
onPressed: () {},
),
I have this AnimatedContainer widget here. My Text() widget and RaisedButton widget are hidden inside the box. They appear as the AnimatedContainer expand. However, my IconButton doesn't.
Also, Icon widget also stays like IconButton widget. How can I make it appear when the AnimatedContainer is stretched like the Text widget?

I've modified your code, hope this is what u want.
class _RowStructureState extends State<RowStructure> {
bool pressed = false;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
pressed = !pressed;
});
print(pressed);
},
child: Column(children: <Widget>[
AnimatedContainer(
height: pressed ? 120 : 50,
color: Colors.green,
duration: Duration(seconds: 1),
child: Stack(
children: [
Container(
height: 50,
width: 50,
color: Colors.black,
),
Positioned(
bottom:0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text('asd'),
IconButton(
padding: EdgeInsets.all(0),
icon: Icon(Icons.ac_unit,),
onPressed: pressed?(){}:null,
),
],
),
)
],
),
)
]),
);
}
}

Related

Animated Container over the contents of another flutter container

I'm trying to make a screen that the blue container is on top of the content of the grey container, but the way I'm doing the blue container is pushing the content of the grey container. How could I make the blue container when expanded to be on top of the grey one? Do I have to use stack? I couldn't understand how I can do it.
class _TestScreenState extends State<TestScreen> {
bool isExpanded = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Title'),
),
body: LayoutBuilder(
builder: (p0, p1) {
final widthScreen = p1.maxWidth;
final heightScreen = p1.maxHeight;
return Column(
children: [
Container(
color: Colors.amber,
width: widthScreen,
height: heightScreen * 0.32,
child: Column(
children: [
Row(
children: [
IconButton(
iconSize: 30,
icon: const Icon(Icons.arrow_back),
onPressed: () {},
),
],
),
],
),
),
Expanded(
child: Container(
height: heightScreen * .5,
alignment: Alignment.bottomCenter,
color: Colors.grey,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("line 1"),
Text("line 2"),
Text("line 3"),
AnimatedContainer(
duration: Duration(milliseconds: 300),
height: isExpanded
? heightScreen - heightScreen * 0.32
: heightScreen * .2,
color: Colors.blue,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
iconSize: 30,
color: Colors.black,
icon: const Icon(Icons.ac_unit),
onPressed: () {
setState(() {
isExpanded = !isExpanded;
});
},
)
]),
],
),
),
],
),
),
),
],
);
},
),
);
}
}
Yes you have to use a Stack:
Columns and Rows only put UI elements next to each other.
Stack(
children: [
BottomWidget(),
MiddleWidget(),
TopWidget(),
]
),
If you want your TopWidget to also be at the top of the screen wrap it with an Align widget.
In your case replace TopWidget() with whatever you want to be on top (probably the blue container).
Also watch this 1 min video about the Stack widget: Stack - Flutter.
In column you should wrap all the widgets with expanded widget and provide flex accourding to the size which you need. Try the code as followed:
Column(
children: [
Expanded(flex: 2, child: Container(color:
Colors.red));
Expanded(flex: 3, child: Container(color:
Colors.green));
Expanded(flex: 1, child: Container(color:
Colors.blue));
]
);
This might solve your issue.
For overlapping Stack is the widget.

How to create a row with 2 buttons that take up the entire row & placed at the bottom of the view/screen

How can I create a row w/2 buttons that, together, take up the space of their parent (the row)? I want to place this row immediately above the bottom navigation bar at times and then at other times I want it to take the place of the bottom navigation bar. Can I do it just using Row? I've tried persistentFooterButtons with a child of Row and children of FractionallySizedBox but it results in an overflow error and the buttons don't take up the height of of the persistentFooterButtons. There's got to be a better, more straight-forward, approach. Just learning Flutter.
This is a rough example of what I want placed at the bottom of the screen (buttons should be of equal height), where the bottom nav bar would be... and/or immediately above.
[![horizontallyAlignedButtonsWithWidthOfRow][1]][1]
Some of the many (unsuccessful attempts) below:
Wrap Buttons in Expand Attempt:
return Row(
children: <Widget>[
Expanded(
child: ElevatedButton(
onPressed: () {},
style: TextButton.styleFrom(backgroundColor: Colors.blue),
child: Text(
"Some Text #1",
style: TextStyle(color: Colors.white),
))),
Expanded(
child: ElevatedButton(
onPressed: () {},
style: TextButton.styleFrom(backgroundColor: Colors.green),
child: Text("Some Text #2"),
),
),
],
Wrap Buttons in Expand Attempt Result:
[![Result][2]][2]
As you can see, there is white space that shouldn't be there and the buttons are evenly spaced. I have also tried using ColoredBoxes instead of buttons as I read that buttons have margins that cannot be changed?
UPDATE
Finally figured it out, with the help of #lava solutions. Just made a few tweaks to it to remove white space, etc.
return Container(
padding: EdgeInsets.all(0.0),
height: 50,
child: Row(
children: [
Container(
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.blue, // background
onPrimary: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.zero),
),
onPressed: () {},
child: Text("Button1"),
),
),
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green, // background
onPrimary: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.zero)),
onPressed: () {},
child: Text("Button2"),
),
),
)
],
),
);
}
}```
[1]: https://i.stack.imgur.com/CydR4.png
[2]: https://i.stack.imgur.com/1JifM.png
Container(
padding: EdgeInsets.all(8.0),
height: 100,
child: Row(
children: [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
)),
Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child:
ElevatedButton(onPressed: () {}, child: Text("Button2")))
],
),
)
Container(
padding: EdgeInsets.all(8.0),
height: 100,
child: Row(
children: [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button2"),
),
),
)
],
),
)
FullCode
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MaterialApp(home: Mainwidget()));
}
class Mainwidget extends StatefulWidget {
const Mainwidget({Key? key}) : super(key: key);
#override
_MainwidgetState createState() => _MainwidgetState();
}
class _MainwidgetState extends State<Mainwidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.all(8.0),
height: 100,
child: Row(
children: [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button2"),
),
),
)
],
),
),
),
);
}
List<Widget> children() {
return [
Expanded(
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {},
child: Text("Button1"),
),
)),
Container(
padding: EdgeInsets.only(left: 8.0),
height: 100,
child:
ElevatedButton(onPressed: () {}, child: Text("Button2")))
];
}
}
You can either add persistentFooterButtons to the Scaffold like
Scaffold(
persistentFooterButtons: [
TextButton(),
TextButton()
]
)
Or in the view:
Column(
children: [
Expanded(child: yourContent), // To use max height space
Row(
children: [
Expanded(child: TextButton()),
Expanded(child: TextButton()),,
]
),
]
),
To give a different width you can add flex to the Expanded or use Flexible and add flex
Wrap both your buttons with Expanded so that they take same amount of width and fill the row.

ListView with Expanded when not scrollable

I want to make a menu with list of ExpansionTile and a footer, when the ExpansionTile is not expanded (not scrollable) the footer stay on the bottom of screen, but when the ExpansionTile is expanded (scrollable) the children of ExpansionTile push the footer out of screen.
For a clearer illustration, please see the following image
this my current code, but it's not a best way I think
checking is scrollable or not
checkIsScrollable(BuildContext context) {
if (Scrollable.of(context).position.minScrollExtent >=
Scrollable.of(context).position.maxScrollExtent) {
setState(() {
scrollable = false;
});
} else {
setState(() {
scrollable = true;
});
}
this the listview
ListView(
padding: EdgeInsets.symmetric(horizontal: 16),
children: [
LimitedBox(
maxHeight: !scrollable
? MediaQuery.of(context).size.height - 84
: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 24,
),
Text(
"Account".toUpperCase(),
style: ThemeApp.appBarTextStyle(),
),
SizedBox(
height: 24,
),
photoProfile(),
SizedBox(
height: 40,
),
menuProfile(),
SizedBox(
height: 40,
),
AccountContent.customerCare1(
context: context,
onExpansionChanged: (_) {
Future.delayed(
Duration(milliseconds: 101),
() {
checkIsScrollable(context);
},
);
},
),
AccountContent.sellWithUs(
context: context,
onExpansionChanged: (_) {
Future.delayed(
Duration(milliseconds: 101),
() {
checkIsScrollable(context);
},
);
},
),
AccountContent.customerCare2(
context: context,
onExpansionChanged: (_) {
Future.delayed(
Duration(milliseconds: 101),
() {
checkIsScrollable(context);
},
);
},
),
!scrollable
? Expanded(
child: Container(),
)
: Container(),
Container(
padding: EdgeInsets.symmetric(vertical: 16),
child: Column(
children: [
InkWell(
child: Row(
children: [
Container(
height: 18,
width: 18,
color: ThemeApp.borderColor,
),
SizedBox(width: 10),
Text(
"LOGOUT",
style: ThemeApp.subTitleTextStyle(),
),
],
),
onTap: () {},
),
SizedBox(
height: 20,
),
Row(
children: [
Expanded(
child: BorderedButton(
child: SvgPicture.asset(
"assets/icons/icon_whatsapp.svg",
color: ThemeApp.primaryColor,
),
onTap: () {
openWhatsapp();
},
),
),
SizedBox(
width: 17,
),
Expanded(
child: BorderedButton(
child: SvgPicture.asset(
"assets/icons/icon_instagram.svg",
color: ThemeApp.primaryColor,
),
onTap: () {
openInstagram();
},
),
),
SizedBox(
width: 17,
),
Expanded(
child: BorderedButton(
child: SvgPicture.asset(
"assets/icons/icon_mail.svg",
color: ThemeApp.primaryColor,
),
onTap: () {
openMail();
},
),
),
],
),
],
),
)
],
),
),
],
);
You should use a Column inside of LayoutBuilder and with a ConstrainedBox, set The minHeight of the Column to maxHeight of LayoutBuilder:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
YourListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
),
YourFooter(),
],
),
),
);
},
);
}
I didn't get your question correctly but i guess you need too use Stack widget which always stays your footer on it's place even your page is Scrollable.
The footer you don't want to scroll, make the Column having two children and inside the column add another column and put the scrollable data inside that and wrap that with the SingleChildScrolView.
Column(
children: [
SingleChildScrollView(
child: Column(
children: [
// your scrollable data here
],
Column(
children: [
// Footer not scrollable
],),
],

Widget on a widget with Centering

I want to put a widget onto other's view.
Here is what I did
In normal version without countdown timer, there is no whitespace inside the screen. It is %50 %50 divided by colours(red and blue).
What I want to do is adding that countdown timer without creating whitespace. Directly adding it onto those colours on the center.
I saw that with Stack it is possible to do. I tried it but couldn't remove the white area.
Here is my code:
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Column(
children: [
Expanded(
flex: 40,
child: new Container(
width: double.infinity,
child: new Column(
children: <Widget>[
box1 = new Expanded(
flex: boxSize1,
child: InkWell(
onTap: () {
clickBox1();
}, // Handle your callback
child: new Container(
alignment: Alignment.topCenter,
color: colorRandom,
),
),
),
TimeCircularCountdown(
unit: CountdownUnit.second,
countdownTotal: 3,
onUpdated: (unit, remainingTime) => print('Updated'),
onFinished: () {
setState(() {
visibility = false;
});
},
),
box2 = new Expanded(
flex: boxSize2,
child: InkWell(
onTap: () {
clickBox2();
}, // Handle your callback
child: new Container(
alignment: Alignment.topCenter,
color: color,
),
),
),
],
),
),
),
],
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Column(
children: [
Expanded(
child: Container(
color: Colors.blue,
)),
Expanded(
child: Container(
color: Colors.red,
)),
],
),
Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: Colors.white,
),
// use your countdown timer widget in child
),
)
],
),
);
}

How can I have two buttons in the bottom using align widget inside the center and column widgets?

I am trying to have a grouped button with two individuals and place them in the bottom. It is a login screen so there are other things.
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 75.0,
),
Text('Login'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.orange,
onPressed: () {
print('login');
},
),
RaisedButton(
onPressed: () {
print('signup');
},
),
],
),
],
),
),
),
);
}
}
I've been trying with like align bottom and stuffs. But with Row(), it does not work with Center + Column widget. How can I send these two buttons to the bottom of the Center widget?
There are multiple ways to do this. One of them is to use the Spacer widget:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 75.0,
),
Spacer(),
Text('Login'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.orange,
onPressed: () {
print('login');
},
),
RaisedButton(
onPressed: () {
print('signup');
},
),
],
),
],
),
),
),
);
Another one would be to reverse the column and start from the bottom, but most probably the side effects are not wanted.
Also, one option would be to divide the whole screen into fixed height partitions with the help of MediaQuery.of(context).size.height value so that your buttons are always at the bottom.
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 75.0,
),
Text('Login'),
Expanded(
child:Container
(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.orange,
onPressed: () {
print('login');
},
),
RaisedButton(
onPressed: () {
print('signup');
},
),
],
),
)
)
],
),
),
),
);
}