How to make a row having icon and text tappable? - flutter

I have 2 questions related :
I have nested function BuildButtonColumn which takes an icon
and text below it and I want to make it tappable. I know
GestureDetector has onTap property, but how do I use that in the
function BuildButtonColumn ?
Column buildButtonColumn(IconData icon, String label) {
Color color = Theme
.of(context)
.primaryColor;
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
),
Icon(icon, color: color),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
label,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: Colors.black,
)
),
)
],
);
}
Widget buttonSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildButtonColumn(Icons.message, 'Message'),
buildButtonColumn(Icons.videocam, 'Request Video')
],
),
);
I took button layout reference from here.
And this is the UI wherein I need to open specific screen on each icon or text tap.
I also want to show a vertical divider between them. I followed
this SO post, but it didn't work out for me or I might have
missed something there to implement it.

Instead return Column you can write:
return GestureDetector(
onTap: (){ ... },
child: Column(),
)
Regarding divider - VerticalDivider() is totally fine for me
Widget buttonSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildButtonColumn(Icons.message, 'Message'),
VerticalDivider(color: Colors.black,),
buildButtonColumn(Icons.videocam, 'Request Video')
],
),
);
It has to work

Related

Flutter: How to have Container/Column with fix height

The layout have uses column with Text and Image. The data change based from a list and some text/image are nil. How to make the container takes the same height when only one data is present?
Thanks.
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
color: Colors.red,
child: Column(
children: [
Text(
'This is Container/Column1. It have two widgets, Text and Image. How to make the height of the container same even if one the the widget is removed/null?',
),
Image.asset('assets/index.jpg')
],
),
),
Container(
color: Colors.green,
child: Column(
children: [
Text('This is Container/Column2. This will have additional widgets.'),
SizedBox(
width: double.maxFinite,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
),
child: Text('Next Button',
),),),],),),],),
first approach: add a fixed height to your container
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
// this will give the container a fixed height of 0.4 from the screen height
height: MediaQuery.of(context).size.height * 0.4,
color: Colors.red,
child: Column(
children: [
Text(
'This is Container/Column1. It have two widgets, Text and Image. How to make the height of the container same even if one the the widget is removed/null?',
),
Image.asset('assets/index.jpg')
],
),
),
Container(
color: Colors.green,
child: Column(
children: [
Text('This is Container/Column2. This will have additional widgets.'),
SizedBox(
width: double.maxFinite,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
),
child: Text(
'Next Button',
),
),
),
],
),
),
],
),
second approach: if one of them is null add a SizedBox() with your prefered height
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.4,
color: Colors.red,
child: Column(
children: [
someCondition ? Text(
'This is Container/Column1. It have two widgets, Text and Image. How to make the height of the container same even if one the the widget is removed/null?',
) : SizedBox(height : 40)
someCondition ? Image.asset('assets/index.jpg') : SizedBox(height : 40)
],
),
),
Container(
color: Colors.green,
child: Column(
children: [
Text('This is Container/Column2. This will have additional widgets.'),
SizedBox(
width: double.maxFinite,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
),
child: Text(
'Next Button',
),
),
),
],
),
),
],
);
One way is to wrap column with Expanded. Second is to have fixed height for contained. If you have this problem with ListView inside another widget and have problems, use shrinkWrap as true inside a ListView. And again for your problem (which person above failed to understand) is that you need or fixed value for height or use Expanded (as much space as possible) or Flexible (least space possible).

how to fix position child widget in row? flutter

I'm trying to make comment card.
There is one problem.
My avatar and button are not fixed when comment height is growing
I want avatar image and button's position fixed.
How can I make this ?
import 'package:flutter/material.dart';
import '../../size_config.dart';
class CommentItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: Row(
children: <Widget>[
CircleAvatar(
radius: 25,
child: ClipOval(
child: SizedBox(
height: 1000,
width: 1000,
child: Image.asset(
'assets/images/img2.jpg',
fit: BoxFit.cover,
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('123',
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 17)),
SizedBox(height: 3),
Text(
'. If you want to keep these changes, it is re',
style: TextStyle(color: Colors.grey),
maxLines: 4,
),
],
),
),
),
ClipOval(
child: Material(
color: Colors.blue, // button color
child: InkWell(
splashColor: Colors.red, // inkwell color
child: SizedBox(
width: SizeConfig.widthMultiplier * 8.8,
height: SizeConfig.heightMultiplier * 5,
child: Icon(
Icons.person_add,
size: SizeConfig.imageSizeMultiplier * 5.5,
color: Colors.white,
)),
onTap: () {},
),
),
)
],
),
);
}
}
it looks like your post is mostly code; please add some more details
it looks like your post is mostly code; please add some more details
it looks like your post is mostly code; please add some more details
To achieve this you can make use of Row's crossAxisAlignment property it will arrange the widget inside the row respectively
For Center -
crossAxisAlignment: CrossAxisAlignment.center
For Top -
crossAxisAlignment: CrossAxisAlignment.start,
For Bottom -
crossAxisAlignment: CrossAxisAlignment.end,
Did you try using the crossAxisAlignment?
Row(
crossAxisAlignment: CrossAxisAlignment.start,
You can do it using...
crossAxisAlignment: CrossAxisAlignment.start
For this, you can use the Alignment Property of Row
There is two alignment property in Row:
MainAxisAlignment
CrossAxisAlignment
MainAxisAlignment is used for Horizontal Alignment of Widgets and CrossAxisAlignment is used for Vertical Alignment.
In your case you need to set:
Row(
crossAxisAlignment: CrossAxisAlignment.start,

What widget should I use for center text and left-aside button

I am making layout for flutter application
What I want to do is
-----------------------
|[i] [text] |
| |
Icon should be the left (padding 5px)
And text should be the center of screen.
At first I should use the Column
However my layout is not the same proportion
It might be simple though , how can I make it??
Stack() is one of the many options that you can use. Something like this:
Stack(
children:<Widget>[
Padding(
padding: EdgeInsets.only(left: 5),
child: Icon(Icons.info),
),
Align(
alignment: Alignment.topCenter,
child: Text("I'm on the top and centered."),
),
],
),
One way you can do this is something like this..
Widget build(BuildContext context) {
return Column(
children: [
Padding(
padding: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.info),
Text('text'),
Opacity(opacity: 0, child: Icon(Icons.info)),
],
),
),
Padding(
padding: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.info),
Text('second text'),
Opacity(opacity: 0, child: Icon(Icons.info)),
],
),
),
],
);
}
Result:
I might be late, but I want this answer to be there, if some one would find it better for the development purposes in future time.
We can make a reusable widget, which we can use it inside the main widget. The widget will accept text, and icon to be passed when called
// IconData is the data type for the icons
Widget myWidget(String text, IconData icon) => Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
// this will be used a left-padding param
SizedBox(width: 20.0),
// using it here
Icon(icon, size: 28.0, color: Colors.greenAccent),
SizedBox(width: 5.0),
// this will take the remaining space, and then center the child
Expanded(child: Center(child: Text(text)))
]
);
To use in the main Widget, just do like this:
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// calling our widget here
myWidget('FirstText', Icons.alarm),
SizedBox(height: 20.0), // this is used as a top margin
myWidget('SecondText', Icons.notifications)
]
)
If you wanna check out the sources which I used, please see:
Expanded class
SizedBox class
The result you will get is this:
This was an answer I gave a while ago for this same issue, but the other situation was vertical (a Column) instead of horizontal (a Row). Just swap the Row and Columns out for a Column and Rows in this example and you'll get the idea.
My code has grey added in order to show the difference between the two approaches.
A Stack will work, but it's overkill for this, this kind of problem is part of why we have Expandeds and Flexibles. The trick is to use three Flexibles (2 Expandeds and a Spacer). Put the Spacer on top. It and the bottom Expanded must have the same flex value in order to center the middle Expanded.
import 'package:flutter/material.dart';
class CenteringOneItemWithAnotherItemInTheColumn extends StatelessWidget {
const CenteringOneItemWithAnotherItemInTheColumn({
Key key,
}) : super(
key: key,
);
/// Adjust these values as needed
final int sameFlexValueTopAndBottom = 40; // 40%
final int middleFlexValue = 20; // 20%
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Column Alignment Question'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Spacer(),
const Text(
'Cent',
style: TextStyle(
fontSize: 64,
),
),
const Spacer(),
const Text(
'Bot',
style: TextStyle(
fontSize: 64,
),
),
],
),
Column(
children: <Widget>[
/// The key is to have the Spacer and the bottom Expanded
/// use the same value for flex. That will cause the middle
/// child of the Column to be centered vertically.
Expanded(
flex: sameFlexValueTopAndBottom,
child: Container(
width: 100,
color: Colors.grey[300],
),
),
Expanded(
flex: middleFlexValue,
child: const Align(
alignment: Alignment.center,
child: Text(
'Cent',
style: TextStyle(
fontSize: 64,
),
),
),
),
Expanded(
flex: sameFlexValueTopAndBottom,
child: Container(
color: Colors.grey[300],
child: const Align(
alignment: Alignment.bottomCenter,
child: Text(
'Bot',
style: TextStyle(
fontSize: 64,
),
),
),
),
),
],
),
],
),
);
}
}

How to add Scrolling Functionality in Scaffold

I'm getting the problem when I add Scrolling functionality in Scaffold, here I have tried SingleChildScrollView, CustomerScrollView, and ListView but it freezes the UI but when I replaced ti Scaffold to LayoutBuilder it works but all the background my UI got black.
I just want to add scrolling functionally to Scaffold.
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
...Some Code...
},
child: Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
mydata[0][i.toString()],
style: TextStyle(fontSize: 16.0, fontFamily: "Quando"),
),
)),
Expanded(
flex: 6,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choiceButton('a'),
choiceButton('b'),
choiceButton('c'),
choiceButton('d'),
],
),
)),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Text(showtimer,
style: TextStyle(
fontSize: 35.0,
fontFamily: "Times New Roman",
fontWeight: FontWeight.w700)),
))
],
),
) // Scaffold
);// WillPopScope
}
Try This
return Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: false,
backgroundColor: Colors.white,
body: Column(
children: <Widget>[
Expanded(
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
],
),
),
),
),
]
Don't use Expanded inside any scrolling container unless you wrap it in a fixed bound on its main axis.
Like in your case main axis is vertical and you are using expanded in it, since expanded needs a bound to limit its expansion, you should've remove that expanded thing or just wrap the container in a SizedBox for a specific height.
Than you can wrap the sized box in any scroll container which suits you.
Hope it helps!
In your code, change Column to ListView, and remove the expanded widget. you can use fixed height or MediaQuery.of(context).size.height * (any ratio) to the containers, or just don't specify any container height so it'll take its children's height.
here's the code will look like:
body: ListView(
shrinkWrap: true,
children: <Widget>[
Container(
// height: MediaQuery.of(context).size.height * (any ratio) / fixed height
child: Text(
mydata[0][i.toString()],
style: TextStyle(fontSize: 16.0, fontFamily: "Quando"),
),
),
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choiceButton('a'),
choiceButton('b'),
choiceButton('c'),
choiceButton('d'),
],
),
),
Container(
alignment: Alignment.topCenter,
child: Text(showtimer,
style: TextStyle(
fontSize: 35.0,
fontFamily: "Times New Roman",
fontWeight: FontWeight.w700)),
)
],
),

Is there a way to align a widget to the far right of a row in Flutter?

I have a row in Flutter with two widgets. I'm trying to keep the first widget centered in the middle of the screen and the second widget forced to the far right of the screen.
I've tried using Spacer(). This results in the app returning a blank screen.
I've also tried using Expanded. This sends the second widget off the screen completely.
Trying mainAxisAlignment: MainAxisAlignment.spaceBetween did not seem to have any effect.
#override
Widget build(BuildContext context) {
return new Container(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Container(
child: new GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Column(
children: <Widget>[
SizedBox(height: 40.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Column(
children: <Widget>[
new Container(
child: Row(
mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(),
Container(
child: Text(
'Profile',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lato',
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
),
Container(
child: IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
size: 30.0,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OnBoarding()),
);
}),
),
]),
),
),
],
),
],
),
You can use a Row with an Expanded child that contains a Stack. Centre your text with Center and position the icon with Positioned, like so:
[...]
child: Column(
children: <Widget>[
SizedBox(height: 40.0),
Row(
children: <Widget>[
Expanded(
child: Stack(
children: [
Center(
child: Text(...),
),
),
Positioned(
right: 8,
child: IconButton(...),
[...]
Simply just add Spacer() between your main text and the Icon you want to the far right.
For example:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
Text(
'Random test text',
style: TextStyle(color: Colors.white),
),
Spacer(),
IconButton(
icon: Icon(Icons.more_vert_rounded),
color: Colors.white,
onPressed: () {},
),
],
)
I hope this helps you. And I hope the format of the code is readable. Still getting a hang of stackoverflow comments
I did this and worked in my project
child:Row(
**crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,**
children: [
Icon(MaterialCommunityIcons.comment_outline),
Text("0"),
Icon(Icons.favorite_border),
Text("0"),
],
),
I needed align Icons and Text at right in Row widget
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end
children: [ // put your widget list and be happy ]
)
)
enter image description here
Use a row with this following structure:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(),
Container(
child: Text(
'Profile',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lato',
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
),
Container(
child: IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
size: 30.0,
),
),
),
]
),
what will happen is that the spaceBetween property will divide available space equally between the widgets in the row, so I put an empty Container, and this will force the Text widget to be in the middle of the row and the IconButton in the far end as you desire.
I noticed in your code snippet that you have a Column with a single Row which again contains a single Column , you should eliminate this redundancy to optimize your code and make it easier to debug:
Have you tried setting the mainAxisAlignment of the row to mainAxisAlignment.center?
Imo the easiest way to do this is to create a row with 2 children: The first child is an Expanded Row with all your "main" widgets. The second child is your widget which must be aligned to the end.
Row(
children: [
Expanded(
child: Row(
children: [...mainWidgets...],
),
),
...endWidget...
],
),
Note that Expanded is space-greedy. If you use e.g. MainAxisAlignment.center for your Expanded Row, then your children are drawn across the whole avialable width. If this is not to your liking, Id suggest to wrap the Expanded-Row (not Expanded) inside a Container with "constraints: BoxConstraints(maxWidth: 500)". Obviously Expanded shouldnt be Constrained.
Achieve using Expanded & Align like below inside Row:
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
...some other widgets,
Expanded(
//Expanded will help you to cover remaining space of Row
flex: 1,
child: Align(
//Align with alignment.centerRight property will move the child to righteous inside Expanded
alignment: Alignment.centerRight,
child: const Icon(Icons.arrow_back),
),
),
],
),
Note, the Expanded has to be just inside the Row children: <Widget>[],
othewise suppose you've put the GestureDetector inside Row children: <Widget>[], and inside GestureDetector you have put your Expanded, then it won't
work.
Hope this would help many one.