Center Align Two Widgets in a Stack - flutter

Coming from Android development, what is the equivalent of 'android:layout_gravity="center_vertical"' in Flutter?
I have two boxes wrapped in a Stack that I would like to center align vertically. However, the size of the largest item is not fixed so I am unable to use any fixed values. This presents some difficulty as I have no way of positioning one child in relation to the other child. In Android, all you have to do is set 'layout_gravity' to 'center_vertical' on the child items.
This is what I have so far. The icon's position is fixed which is not good.
class CardItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new SizedBox(
width: double.infinity,
child: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(72.0, 6.0, 12.0, 6.0),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: 150.0,
),
child: Material(
elevation: 8.0,
borderRadius: BorderRadius.circular(12.0),
color: Colors.white,
child: InkWell(
onTap: () => {},
child: Padding(
padding: EdgeInsets.fromLTRB(76.0, 24.0, 6.0, 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text('Computer',
style: Theme.of(context).textTheme.headline),
Text('电脑',
style: Theme.of(context).textTheme.subhead.apply(fontWeightDelta: -2)
),
],
),
),
),
),
)
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.fromLTRB(12.0, 0.0, 0.0, 0.0),
child: SizedBox.fromSize(
size: Size.fromRadius(60.0),
child: Material(
elevation: 12.0,
shape: CircleBorder(),
child: Image.asset('image.png'),
),
),
),
),
],
)
);
}
}

Wrap it in an Align widget...
Align(
alignment: Alignment.center,
child: Positioned(
top: 10,
child: Text('hi'),
),
),

Related

Flutter: perfectly align Icons to the edge

I am trying to align the icon to the very left edge of the blue container.
The red container is just there for reference (I am using ScreenUtil).
How can I align the icon perfectly to the left edge of the blue container? So that there is no gap, not even one pixel? In this snippet I used FaIcons, however I have the same problem with the standard material icons.
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
left: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 50.w,
color: Colors.blue,
margin: EdgeInsets.only(left: 35.w),
child: IconButton(
iconSize: 25.w,
onPressed: () {},
icon: const FaIcon(FontAwesomeIcons.bars),
),
),
Container(
margin: EdgeInsets.only(left: 35.w),
color: Colors.red,
width: 20.w,
height: 20.w,
)
],
),
),
);}}
remove the padding from iconbutton and set constraints.
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
left: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 50,
color: Colors.blue,
margin: EdgeInsets.only(left: 35),
padding: EdgeInsets.zero,
alignment: Alignment.centerLeft,
child: IconButton(
iconSize: 25,
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
onPressed: () {},
icon: const Icon(Icons.person,),
),
),
Container(
margin: EdgeInsets.only(left: 35),
color: Colors.red,
width: 20,
height: 20,
)
],
),
),
);
}
I think it's fine
Container(
width: 50.w,
color: Colors.blue,
padding: EdgeInsets.zero,
margin: EdgeInsets.only(left: 35.w),
child: IconButton(
iconSize: 25.w,
alignment: Alignment.centerLeft,
padding: EdgeInsets.zero,
onPressed: () {},
icon: Icon(Icons.menu),
),
),

ScrollView RenderFlex overflow - Flutter

I'm new to Flutter and have been trying to clone a screen that requires a scroll architecture.Here is the link of the screen that i'm working on. https://i.stack.imgur.com/1OW2b.pngThe code is as below.PS: Ignore the fields that are incomplete. As soon as I get the scroll view, i'll add the functionalities afterwards.
Scaffold(
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: const <Widget>[
Icon(Icons.menu),
Image(), //Asset image
],
),
Row(
children: <Widget>[
const Icon(Icons.notifications_none),
const SizedBox(width: 27.0),
CircleAvatar(
child: Text("JM"),
),
],
)
],
),
Row(
children: const <Widget>[
Icon(Icons.arrow_back),
SizedBox(width: 20.0),
Text("Public page"),
],
),
const SizedBox(
height: 20.0,
),
const Text(" Please fill the form following the proper order."),
const SizedBox(height: 10.0),
OverviewWidget(), //Widget with lots of TextFormField
SizedBox(height: 10.0),
DescriptionWidget(), //Widget with lots of TextFormField
],
),
),
Align([enter image description here][1]
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: () {
print("Hello");
},
child: Container(
height: 130.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 10,
spreadRadius: 1,
)
],
),
child: Container(
margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
decoration: BoxDecoration(
color: Colors.green.shade400,
borderRadius: BorderRadius.circular(35),
),
child: const Padding(
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 150.0,
),
child: Text(
"Save",
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w600),
),
),
),
),
),
),
],
),
);
So far, i've only created the Overview and Description widgets and i'm already getting RenderFlex overflow error. I tried wrapping the very first Column widget with a SingleChildScrollView widget but it can be noticed that the Save button at the bottom should stay fixed. I tried wrapping the whole widget with Stack widget instead of a Column widget but it didn't help either. I also used ListView widget but got the same results.What shall I do to achieve this view?
I guess you had all the elements but did not quite manage to use them as needed.
Your screen is composed of two important layout:
A stack (containing a button on top of a scrollable widget)
The scrollable widget
The stack has to be a stack, the scrollable can be anything but in your case SingleChildScrollView+Column seems the best choice.
Here is the concrete implementation:
Scaffold(
body: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(bottom: 100.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.menu),
Container(
height: 100,
width: 100,
color: Colors.redAccent,
),
//Asset image
],
),
Row(
children: <Widget>[
const Icon(Icons.notifications_none),
const SizedBox(width: 27.0),
CircleAvatar(
child: Text("JM"),
),
],
)
],
),
Row(
children: const <Widget>[
Icon(Icons.arrow_back),
SizedBox(width: 20.0),
Text("Public page"),
],
),
const SizedBox(
height: 20.0,
),
const Text(" Please fill the form following the proper order."),
const SizedBox(height: 10.0),
Container(
height: 400,
color: Colors.blueAccent,
), //Widget with lots of TextFormField
SizedBox(height: 10.0),
Container(
height: 400,
color: Colors.greenAccent,
), //Widget with lots of TextFormField
],
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: () {
print("Hello");
},
child: Container(
height: 130.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 10,
spreadRadius: 1,
)
],
),
child: Container(
margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
decoration: BoxDecoration(
color: Colors.green.shade400,
borderRadius: BorderRadius.circular(35),
),
child: const Padding(
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 150.0,
),
child: Text(
"Save",
style: TextStyle(
color: Colors.white, fontSize: 17, fontWeight: FontWeight.w600),
),
),
),
),
),
),
],
),
)
Note that you have to put a bottom padding inside the SingleChildScrollView to take into account the button. This is fine in your case since the button has a static height. However if you need something more fancy you might want to check How to create a scroll view with fixed footer with Flutter? as #Csisanyi suggested
Consider wrapping the Column with an Expanded widget
You can also check out this flutter doc. It addresses this common issue in detail.
https://flutter.dev/docs/testing/common-errors
Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.menu),
// Image(), //Asset image
Image.asset(
'assets/ocean.jpg',
height: kToolbarHeight,
/// make sure of image height
fit: BoxFit.fitHeight,
),
],
),
Row(
children: <Widget>[
const Icon(Icons.notifications_none),
const SizedBox(width: 27.0),
CircleAvatar(
child: Text("JM"),
),
],
)
],
),
Row(
children: const <Widget>[
Icon(Icons.arrow_back),
SizedBox(width: 20.0),
Text("Public page"),
],
),
const SizedBox(
height: 20.0,
),
const Text(
" Please fill the form following the proper order."),
const SizedBox(height: 10.0),
//todo: OverviewWidget(), //Widget with lots of TextFormField
...List.generate(22, (index) {
return TextField(
decoration: InputDecoration(hintText: "1st $index"),
);
}),
SizedBox(height: 10.0),
//todo: DescriptionWidget(), //Widget with lots of TextFormField
...List.generate(22, (index) {
return TextField(
decoration: InputDecoration(hintText: "2st $index"),
);
}),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: () {
print("Hello");
},
child: Container(
height: 130.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 10,
spreadRadius: 1,
)
],
),
child: Container(
margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
decoration: BoxDecoration(
color: Colors.green.shade400,
borderRadius: BorderRadius.circular(35),
),
child: const Padding(
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 150.0,
),
child: Text(
"Save",
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w600),
),
),
),
),
),
),
],
),
),
),

What is the best flutter widget to use to achieve this kinda layout?

This is the UI I want to implement, I only started playing with flutter last week so I am not as fluent. I was wondering what is the best way to achieve this layout.
This is what I get with a stack and column:
This is the code:
Column(
children: <Widget>[
Expanded(
child: Container(
constraints: BoxConstraints.expand(height: 150),
color: Colors.blue,
child: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
bottom: -40,
left: MediaQuery.of(context).size.width * 0.4,
// alignment: Alignment.bottomCenter,
child: Container(
constraints: BoxConstraints.expand(height: 80, width: 80),
color: Colors.green,
),
),
],
),
),
flex: 3,
),
Expanded(
child: Container(
margin: EdgeInsets.all(15.0),
color: Colors.red,
),
flex: 7,
)
],
);
I made something like the image you provided with dummy image and some icon you can change icons if you want,use media query size instead of fixed padding tops
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Column(
children: [
Stack(children: [
Container(
child: FittedBox(
fit: BoxFit.fill,
child: Image.network('https://picsum.photos/300?image=10')),
height: 150,
width: double.infinity,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Padding(
padding: const EdgeInsets.only(top: 75),
child: MaterialButton(
onPressed: () {},
elevation: 2.0,
color: Colors.red,
child: Icon(
Icons.message,
size: 27.0,
),
padding: EdgeInsets.all(20),
shape: CircleBorder(),
),
),
Padding(
padding: const EdgeInsets.only(top: 75),
child: Column(children: [
CircleAvatar(
radius: 55.0,
backgroundImage:
NetworkImage('https://i.pravatar.cc/150?img=54'),
backgroundColor: Colors.transparent,
),
Text("David Beckham"),
Text("Model/SuperStar")
]),
),
Padding(
padding: const EdgeInsets.only(top: 75),
child: MaterialButton(
onPressed: () {},
elevation: 2.0,
color: Colors.blue,
child: Icon(
Icons.add,
size: 27.0,
),
padding: EdgeInsets.all(20),
shape: CircleBorder(),
),
),
],
),
]),
Container(height: 100, color: Colors.red),
Container(height: 100, color: Colors.green),
Container(height: 100, color: Colors.yellow),
Container(height: 100, color: Colors.blue),
],
)));
}
}

Flutter show icon overlap with column

I need to show the avatar and a column in a row which look like overlapping each other.
Something like this
I have done with the left side but don't know how can I add this type of icon which seems like overlapping with my column here is my code
Widget build(BuildContext context) {
double statusBarHeight = MediaQuery.of(context).padding.top;
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Scaffold(
body: Container(
width: double.infinity,
color: Color(0xff1b4881),
child: Column(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: height * 0.05,
),
Container(
padding: EdgeInsets.only(left: 10),
alignment: Alignment.topLeft,
child: new SizedBox(
child: FloatingActionButton(
backgroundColor: Colors.white,
child: Icon(Icons.arrow_back_ios, color: Color(0xff1b4881),),
onPressed: () {
Navigator.pop(context);
},
))),
SizedBox(
height: height * 0.03,
),
Container(
padding: EdgeInsets.only(right: 20),
color: Colors.white,
width: width * 0.7,
height: height * 0.1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Rtn.XYZZ',
style: TextStyle(fontSize: 22),
),
Text(
'President',
style: TextStyle(fontSize: 22),
)
],
),
),
],
),
],
)),
);
}
Try this
Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Container(
height: 60,
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(top: 20, bottom: 20, right: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('AskNilesh'),
Text('AskNilesh'),
],
),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20.0))),
),
Positioned(
right: 0,
top: 0,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(50.0)),
child: Container(
height: 100,
width: 100,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(50.0))),
),
),
)
],
),
)
OUTPUT
you can the Stack Widget to overlap widgets:
Stack(
children: <Widget>[
Column(
children: <Widget>[
Text('Rtn.xxx'),
Text('secretory'),
],
),
Positioned(
left: 10,
right: 10,
top: 10,
bottom: 10,
child: CircleAvatar(
child: Image.asset('blablabla.png'),
),
)
],
)
then play with values of top, left, right, button in the Positioned widget to align the item exactly as you want it.

How can I make InkWell's splash visible?

Environment
Flutter 1.12.13+hotfix.9
Dart 2.7.2
Question
I made code like this below.
I find when I tap it, 'InkWell.onTap' shows up in the console, but splash animation (= the animation expanding like a wave) does not happen. Could you help me understand why I cannot see splash animation?
Sample
InkWell(
splashColor: Colors.blueAccent,
onTap: () {
print('${DateTime.now()}| InkWell.onTap');
},
child: Container(
color: Colors.lightBlue[100],
child: Row(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: Colors.lightBlue[50],
border: Border.all(),
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Text1'),
),
),
),
),
Padding(
padding: EdgeInsets.only(
left: 16, top: 8, right: 8, bottom: 8),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Text2'),
),
),
],
),
),
],
),
),
)
Additional info
The code above only makes a light blue square which you can find 5 in the screenshot.
One person suggested this question is a possible duplicate of this. However, I still have a problem.
I think the answers basically say that "Move the color property to outside of InkWell Widget", but my case has multiple colors (Colors.lightBlue[100] and Colors.lightBlue[50]), so I cannot simply move color to outside. Please correct me if I misunderstand something.
To get the ripple effect a Material widget must be a direct ancestor of InkWell with the placement of your InkWell right now your entire screen would have a ripple effect I am not sure if this is the effect you wanted or not.
Material(
color: Colors.lightBlue[100],
child: InkWell(
splashColor: Colors.blueAccent,
onTap: () {
print('${DateTime.now()}| InkWell.onTap');
},
child: Row(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: Colors.lightBlue[50],
border: Border.all(),
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Text1'),
),
),
),
),
Padding(
padding: EdgeInsets.only(
left: 16, top: 8, right: 8, bottom: 8),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Text2'),
),
),
],
),
),
],
),
),
),