What is Constraint layout's equivalent in Flutter? - flutter

Can I position a widget based on another widget?
like this:
Tiled Layout
Without
flutter_staggered_grid_view Library

There is no Widget similar to ConstraintLayout but you can achieve what you want using different widgets, like this example:
class Testing2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Row(
children: <Widget>[
Flexible(
child: Column(
children: <Widget>[
Flexible(
flex: 1,
child: Container(
color: Colors.deepOrange,
),
),
Flexible(
flex: 2,
child: Container(
color: Colors.lightBlue,
),
),
],
),
),
Flexible(
child: Column(
children: <Widget>[
Flexible(
flex: 3,
child: Container(
color: Colors.orange,
)),
Flexible(
flex: 1,
child: Row(
children: <Widget>[
Flexible(
flex: 2,
child: Container(
color: Colors.blue,
)),
Flexible(child: Container(color: Colors.green))
],
),
)
],
),
)
],
),
);
}
Also you can take a look this link to know about Layout Widgets: https://flutter.io/widgets/layout/

You can try this:
https://github.com/hackware1993/Flutter-ConstraintLayout
Build flexible layouts with constraints, Similar to Android ConstraintLayout.
No matter how complex the layout is and how deep the dependencies are, each child element of ConstraintLayout will only be measured once, This results in extremely high layout performance.

Related

how can i set the size of the child inside the row?

I want to make children use flexible sizes
how can i set the size of the child inside the row? can you guys help me? and find the error constraint
anyone help me
return SafeArea(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
color: Colors.lightBlue,
child: Row(
children: [
Expanded(
flex: 5,
child: Container(
color: Colors.green,
),
),
Expanded(
flex: 5,
child: Container(
color: Colors.blue,
),
)
],
),
)
],
),
)
],
),
);
To place children in a row you can use Flexible widget. The value of flex defines how much space each child should take. In the example that you provided.. Both children will be equally spaced since you gave flex value 5 for both.
return Scaffold(
body: Center(
child: SizedBox(
height: 50,
child: Row(
children: [
Flexible(
flex: 5,
child: Container(
color: Colors.red,
)),
Flexible(
flex: 5,
child: Container(
color: Colors.green,
)),
],
),
),
),
);
If you change the flex value to 1 and 5.. Now the total divisions will be 6 and out of that the first child will take 1 part and the second child will take 5 parts like below
return Scaffold(
body: Center(
child: SizedBox(
height: 50,
child: Row(
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.red,
)),
Flexible(
flex: 5,
child: Container(
color: Colors.green,
)),
],
),
),
),
);
Also if you use a singleChildScrollView and an expanded inside that it then the expanded widget has no bounds so it will throw an error. So wrapping the Expanded with a SizedBox with a specific width will give you expected results.
EDIT
To have a SingleChildScrollView with dynamic content in the row you can do this
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize : MainAxisSize.min,
children:[
SizedBox(
width: 100,//this is important since its a row and the row will take full width and throw an error.
child: Image.asset(""),
),
//Another SizedBox or Text or any widget..
]
)
)

Expanding a widget horizontally inside column

I'm facing some problem by composing layout of my App.
My widget at the end sould look like this
This is my code
Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
children: [
// Widget A
SizedBox(
height: widget.screenHeight * 0.9,
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.red,
),
),
),
// Widget B
Container(
height: widget.screenHeight * 0.1,
color: Colors.green,
)
],
),
// Widget C
Expanded(
child: Container(
color: Colors.pink,
),
)
],
)
I want Widget A to occupy 90% of screen height and mantain a 16/9 aspect ratio, Widget B to occupy remaining 10% height and have the same width of his sibling, and Widget C to fill remaining space
With that code, Widget A and Widget C are showed correctly, but widget B doesn't fill his space as i expect.
What's wrong?
Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
flex: 2,
child: Column(
children: [
Expanded(
flex:4,
child: Container(
color: Colors.yellow,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
),
)
],
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.green,
),
),
],
),
)
],
),
you have to play with the expanded widget

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

Creating a Card with a center icon and bottom row

I'm new to Flutter and I'm attempting to create a Card that has a bottom row and a center Icon or Text. I'm sure this is pretty easy, but I'm struggling . I'm not sure of the best way to do this. Should I create a column with two nested columns?
import 'package:flutter/material.dart';
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Card(
elevation: 5,
margin: EdgeInsets.fromLTRB(16, 16, 16, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.blue,
),
Row(
children: <Widget>[
Expanded(
child: Container(
height: 50,
color: Colors.blue,
),
)
],
)
],
),
),
);
}
}
Try out this code.
Column(
children: <Widget>[
Expanded(
child: Center(
child: Text('\$250'),
),
),
Text('\$ Total'),
],
)
I'm using Expanded to use entire space of container (Column) which will push text to the bottom. And using Center to put a widget (Text in this code) in the middle of the container.

Flutter - Vertical Divider and Horizontal Divider

In Flutter, is there an option to draw a vertical lines between components as in the image.
Not as far as I know. However, it is quite simple to create one — if you look at the source for Flutter's Divider you'll see that it is simply a SizedBox with a single (bottom) border. You could do the same but with dimensions switched.
Update (Oct 4, 2018): a VerticalDivider implementation has been merged in by the Flutter team. Check out the docs but it's very simple to use — simply put it between two other items in a row.
Note: If you are using VerticalDivider as separator in Row widget then wrap Row with IntrinsicHeight , Container or SizedBox else VerticalDivider will not show up. For Container and SizedBox widget you need define height.
As of 10 days ago, flutter has merged a VerticalDivider implementation. It will be available in the default channel very soon, but for now you have to switch to the dev channel to use it: flutter channel dev.
Here is a example of how to use it:
IntrinsicHeight(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('Foo'),
VerticalDivider(),
Text('Bar'),
VerticalDivider(),
Text('Baz'),
],
))
Vertical divider:
As a direct child:
VerticalDivider(
color: Colors.black,
thickness: 2,
)
In a Row:
IntrinsicHeight(
child: Row(
children: [
Text('Hello'),
VerticalDivider(
color: Colors.black,
thickness: 2,
),
Text('World'),
],
),
)
Horizontal divider:
As a direct child:
Divider(
color: Colors.black,
thickness: 2,
)
In a Column:
IntrinsicWidth(
child: Column(
children: [
Text('Hello'),
Divider(
color: Colors.black,
thickness: 2,
),
Text('World'),
],
),
)
import 'package:flutter/material.dart';
class VerticalDivider extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Container(
height: 30.0,
width: 1.0,
color: Colors.white30,
margin: const EdgeInsets.only(left: 10.0, right: 10.0),
);
}
}
Try to wrap it inside the Container with some height as
Container(height: 80, child: VerticalDivider(color: Colors.red)),
Tried with VerticalDivider() but cannot get any divider. I Solved it with
Container(color: Colors.black45, height: 50, width: 2,),
You can use a vertical divider with a thickness of 1.
VerticalDivider(
thickness: 1,
color: Color(0xFFF6F4F4),
),
And if you can't see the vertical divider wrap the row with a IntrinsicHeight widget.
Just wrap your Row in IntrinsicHeight widget and you should get the desired result:
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('Name'),
VerticalDivider(),
Text('Contact'),
],
))
As #rwynnchristian suggested, this seems to be the simplest solution IMO. Just leaving the code here:
import 'package:flutter/material.dart';
class VerticalDivider extends StatelessWidget {
#override
Widget build(BuildContext context) => RotatedBox(
quarterTurns: 1,
child: Divider(),
);
}
add this method anywhere.
_verticalDivider() => BoxDecoration(
border: Border(
right: BorderSide(
color: Theme.of(context).dividerColor,
width: 0.5,
),
),
);
now wrap your content in container
Container(
decoration: _verticalDivider(),
child: //your widget code
);
Use Container for divider is easy, wrap your row in IntrinsicHeight()
IntrinsicHeight(
child: Row(
children: [
Text(
'Admissions',
style: TextStyle(fontSize: 34),
),
Container(width: 1, color: Colors.black), // This is divider
Text('another text'),
],
),
You need to wrap VerticalDivider() widget with the IntrinsicHeight widget. Otherwise, the vertical divider will not show up. And to gain some padding over the top and bottom you can add indent.
IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: VerticalDivider(
thickness: 0.8,
color: Colors.grey,
),
),
Flexible(
child: Text(
"Random Text",
style: TextStyle(
fontSize: 12,
color: AppColor.darkHintTextColor,),
),
),
],
),
)
I guess i found a more robust solution when dealing with this problem;
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
decoration: BoxDecoration(borderRadius: BoxRadius.circular(),color: Colors.gray),
height: 5,
margin: CustomPaddings.horizontal(),
),
),
Text(
"TEST",
style: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(
color: Colors.black,
fontWeight: FontWeight.bold),
),
Expanded(
child: Container(
decoration: BoxDecoration(borderRadius: BoxRadius.circular(),color: Colors.gray),
height: 5,
margin: CustomPaddings.horizontal(),
),
),
],
),
),
Try RotatedBox in combination with a divider to get it vertical, RotatedBox is a widget of flutter that automatically rotates it's child based on the quarterTurn property you have to specify. Head over to here for a detailed explanation https://docs.flutter.io/flutter/widgets/RotatedBox-class.html