I am using below Row widget in flutter , which is nested in a Column widget and on screen it appears shared in the screenshot
I want to the Row elements to appear at extreme ends with some padding. How can I do that?
Row(
children: [
SizedBox(width:20,),
Text("Mark ALL READ"),
SizedBox(width:200,),
Text("Clear All"),
],
),
Setting the mainAxisAlignment property of the row to MainAxisAlignment.spaceAround should place the elements on both ends of the row.
To add some padding you should be able to just place the whole Row() widget into a Padding() widget.
Related
I currently create an editor, which allows to insert new items at certain places in a two dimensional plane.
The editor places items on the screen and wraps them in GestureDetector() or DragTarget() to allow to drop in new editor items.
Therefore, structures like this appear often, to show editable items in a property inspector widget, if the user clicks on the Expanded() Widgets area:
Column(
children: [
DragTarget(
builder: (context, candidateData, rejectedData) {
return Expanded(
child: Text( 'X' ),
);
},
)
],
)
This, as well as GestureDetector(), generates this render error:
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of
type FlexParentData to a RenderObject, which has been set up to accept
ParentData of incompatible type ParentData.
Usually, this means that the Expanded widget has the wrong ancestor
RenderObjectWidget. Typically, Expanded widgets are placed directly
inside Flex widgets. The offending Expanded is currently placed inside
a MetaData widget.
If I remove the DragTarget(), the tree renders fine:
Column(
children: [
Expanded(
child: Text( 'X' ),
)
],
)
Q How to make an Expanded() a DragTarget() or a GestureDetector() child?
Needless to note, that the problem appears with any compile target.
Since the editor allows to drop widget like Column, Card etc., I need a generic solution.
As the documentation says:
Using an Expanded widget makes a child of a Row, Column, or Flex
expand to fill the available space along the main axis (e.g.,
horizontally for a Row or vertically for a Column).
That means you can only use the Expanded widget as direct child of a Row, Column or Flex. That is also why your snippet works without the DragTarget since in that case the Expanded is a direct child of your Column.
To fix your problem you could do something like this:
Column(
children: [
DragTarget(
builder: (context, candidateData, rejectedData) {
return Column(
children: [
Expanded(child: Text( 'X' ))
]
);
},
)
],
)
You could also wrap your DragTarget into an Expanded widget. It's hard to help you exactly without more information. But both ways atleast wont return an error.
I had a very basic Flutter layout which looked something like this:
Column
widget1
expanded
widget2
This worked great. Widgets 1 and 2 were rendered and my main "expanded" widget was taking the rest of the screen, great!
Next I wanted to add two buttons on each side of my expanded widget. So I tried this:
Column
widget1
Row
button1
expanded
button2
widget2
Now Flutter throws a layout error: failedAssertion: size.isFinite
Reading about it online, people are saying you cannot put an Expanded inside a Row or a Column because they use infinite main axis length, so if the child is also infinite this causes problems. However, I already had Expanded inside a Column and that worked fine! Why is putting it inside a Row problematic?
One SO suggestion was to put mainAxisSize: MainAxisSize.min in the Row, but that does not help.
Some of the other suggestions were to put the widget inside a Container with fixed sizes. This does resolve the error, but now the widget goes off screen. And this sort of defies the whole purpose of Flutter responsive UI. Why would anyone want to create a fixed sized object on a platform where screen sizes vary widely?
What am I doing wrong here? Seems I am misunderstanding something fundamental here...
it works fine and doesn't through any error
Column(
children:[
Container(
height:50,
width:50,
color:Colors.red),
Row(
children:[
Container(
height:50,
width:50,
color:Colors.red),
Expanded(
child:Text('hgdhj hdgakhjgck dgfkejg')
),
Container(
height:50,
width:50,
color:Colors.red),
]),
Container(
height:50,
width:50,
color:Colors.red),
])
I want to built a split screen for larger devices. One half should be as small as possible but as large as needed and the other half should occupy the rest of the screen.
I figured I'd use a Row containing two Scaffolds (one wrapped in a Expanded widget) like so:
Row(children: [
Scaffold(appBar: MyAppBar1(), body: Container()),
Expanded(child: Scaffold(appBar: MyAppBar2(), body: Container())),
])
However, I get the following error message when wrapping a Scaffold inside a Row:
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
I know that I could just wrap the Scaffold inside a SizedBox with a fixed width, but I want the Scaffold to automatically take the right size.
Scaffold itself doesn't have a width constraint, so it will try to occupy as much space as possible (if I'm remembering correctly), and Row on its part won't try to constrain it, hence the error.
You have two options:
wrap the Scaffold in another Expanded, then use the flex argument on both the Expanded to give them size relative to each other (i.e., if one has flex: 1 and the other flex: 2, the second one will have twice the size of the first)
wrap the Scaffold in a ConstrainedBox and set the constraints yourself, which I guess in this case would be the maxWidth set on the smaller side
As others pointed out, anyway, if you don't really need another Scaffold, you can simply use two Column and get a similar result.
You do not need to use two Scaffolds. Use two columns inside one Column in Scaffold. Wrap the second Column with Expanded. This way your first part will take as much space as needed and the second part will take the remaining space.
home: Scaffold(
body: Column(
children: [
Column(
children: [],
),
Expanded(
child: Column(
children: [],
),
),
],
),
)
I have a Stack with two Columns.
First column contains contains only one child (1) with InteractiveViewer which has defined height (for example 250). It changes its content's zoom and translation based on scroll offset of SingleChildScrollView from second column. It shouldn't be pushed out of the screen while scrolling, so it's under the scroll view in a stack.
The second column have SingleChildScrollView with top padding (2) OR first view (3) that matches the (1) height.
Now I'd like to make the top padding (2) or view (3) not scroll the SingleChildScrollView but pass those touch events to InteractiveViewer. Doesn't matter whether the solution use padding or empty view, I just wanted to note here than what I want can be achieved with padding or view. I tried both but failed.
I tried the GestureDetector, IgnorePointer and AbsorbPointer, but seems like the SingleChildScrollView always get the touch events. I haven't found a way to make the top padding not scrollable too.
Basically I'd like to achieve something similar to the attached gif, except that I don't need the "Collapsing Header" text animation and app bar. Just pay attention to the mountains that hide below the scroll view. The scroll view should take entire screen once the scroll offset is equal padding/view height (250 in this example).
Is that possible somehow? My logic behind InteractiveViewer is way more complicated than the example provided below, I just simplified it to make the question easier to understand.
Stack(children: [
Column(
children: [
Container( // (1) Widget that should get the touch events
height: 250,
child: InteractiveViewer(...)
),
],
),
Column(
children: [
Expanded(
child: SingleChildScrollView(
padding: EdgeInsets.only(top: 250), // (2) Either not scrollable padding
child: Column(
children: [
Container(height: 250), // (3) or not scrollable first item
Container(...)
],
),
),
),
],
),
]);
I have a list I'm mapping:
List<Widget> names = post.names
.map(
(c) => new Padding(
padding: EdgeInsets.all(8),
child: new Text('' + c['name']),
),
)
.toList();
And displaying:
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: names,
),
However, the row overflows to right if it has too many items in it. I tried to wrap it to Expanded / Flexible widgets, but that causes error about the parent widget not having height.
If I try to use:
crossAxisAlignment: CrossAxisAlignment.stretch,
I get:
BoxConstraints forces an infinite height.
I also tried to use Expanded inside the Row, however that is not possible as I'm creating the children from the list and that causes error.
How to achieve a name list which also expands vertically based to amount of items?
You need to use Wrap instead of Row like this.
Wrap(
children: names,
//...
),
If you want the widgets to be scrollable horizontally, use a list view and set the axis to horizontal.
But if you want the widgets to wrap, then you need to build a grid instead of a row.
Check out this post: Flutter - Layout a Grid