Scale down all children in widget by a factor based on the parent size - flutter

In Flutter I am implementing "what's new" screens which will show a preview of the real screens in the app.
For that I reuse the screen Widgets in the "what's new" flow.
The preview will be shown in a smaller Container and not cover the whole screen.
I want to scale down the text sizes, line heights, etc. for all widgets within this Container to match the smaller bounds.
Is there a way to do this without individually adding a smaller style for every Widget separately?
e.g. scale down all fontSizes by 20% for a Widget child regardless of the size set in the theme

I found the solution. Wrapping the child widget tree with Transform.scale(...) will scale all the Widgets down the tree according to the supplied scale factor.
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Transform.scale(
scale: 0.9,
child: MyScaledWidgetTree(),
),
Container(
child: ...,
),
],
)

Related

Wrap Scaffold in Row

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: [],
),
),
],
),
)

Make first item (or padding) of SingleChildScrollView not scrollable and delegate the touch events

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

"RenderStack object was given an infinite size during layout" when using Positioned inside a Stack

I'm creating a widget that presents a Stack inside a Container. Inside the Stack there is a dynamic Column inside a Positioned widget, which sticks the Column to the Bottom.
I am trying to wrap the Stack in a SingleChildScrollView, that if the dynamic Column will have lots of children it will be able to scroll.
But after I add the scroll view I get this error message:
RenderStack object was given an infinite size during layout.
A scrollView doesn't have height, it will use infinite height for it's children. So the stack should be wrapped in a sizedBox widh a known height in case that you want that. If you want the stack to fill the screen then remove the singleChildScrollview completely. And if you want the stack to be scrollable from the inside. Just add SingleChildScrollView inside the stack
return Scaffold(
body: Container(
color: Colors.blue[100],
child: Stack(
children: [
Positioned.fill(child: SingleChildScrollView(child: MyColumn()))
],
),
),
);
EDIT 1:
Ok the problem is the layout itself. Since you only use the stack to position the image. And you know the widht and height of the image, and the background shape fills all the items. We could
Isolate the stack only to the image, and use padding and some calculation to have the layout build in a similar way.
Then render everything else inside a normal column
My implementation https://dartpad.dev/230b14d8f0b22b45929a75c208786257
From the RenderStack documentation:
First, the non-positioned children (those with null values for top, right, bottom, and left) are laid out and initially placed in the upper-left corner of the stack. The stack is then sized to enclose all of the non-positioned children. If there are no non-positioned children, the stack becomes as large as possible.
Since all of your Stack's children are positioned, Stack will match the maximum size constraint passed down by the SingleChildScrollView. This size has infinite height, so the Stack is forced to have infinite height as well.
To fix this, you will need to find another way to accomplish what you want. One option that comes to mind involves a ConstrainedBox providing a minimum height (obtained from a LayoutBuilder), a non-positioned Column, and a bottomCenter alignment on the Stack itself. This is similar to the first code sample in the SingleChildScrollView documentation:
LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
// This ensures that the Stack fills the entire viewport,
// even if the Column is small.
constraints: BoxConstraints(
minHeight: constraints.maxHeight,
),
child: Stack(
// Place the only non-positioned child (the column) at the bottom
alignment: Alignment.bottomCenter,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [ /* ... */ ]
)
]
)
)
);
}
)

Scrolling Widget inside a Constant size Container flutter web

Hi all fellow developers,
I am developing a responsive web page in flutter using the flutter web SDK, but i am stuck at one part of the page where i have a Row inside row I have 2 Containers among which i want the 1st Container to be Scrollable and the Second container to be of constant size(Non scrollable) just like whatsapp web ui where contact list keeps scrolling but the chat side and the rest of the page doesn't.
please Help me,
Thanks in advance...
This should work You need a fixed sized container and make sure a Scroll able widget should be inside it. Now size can be made responsive by using Media Query Parameters and below code you only need to adjust space and sizing and it would work.
Row(
//Your parent Row
children: [
Container(
//static non scrollable container
child: Column(
children: [
//Children you want to add
//this wont be scrollable
//It is also preferred that you give this some height or width too
],
),
),
Container(
//Scrollable container
//Please adjust height and width yourself
//You can use media query parameters to make it responsive
width: 200,
height: 500,
child: SingleChildScrollView(
//You can also change the scroll direction
child: Column(
//Add children you want to be in
//Scrollable column
),
),
)
],
),

How to use flex parameter in Flexible widget in Flutter?

When there is excess space between widgets, the flex property works as expected.
As mentioned in the documentation, the formula to use is as follows
remainingSpace * (flex / totalOfAllFlexValues)
But when you have to shrink the widgets, the flex property stops making sense.
Giving results like this.
Building on this, here the widgets overflow, so I use flex to shrink box 1 and 2
and while playing with the flex values, the following happens
class Caja extends StatelessWidget {
Color color;
int numero;
double ancho;
Caja(this.color, this.numero, this.ancho);
#override
Widget build(BuildContext context) {
return Container(
width: this.ancho,
height: this.ancho,
color: this.color,
child: Center(
child: Text(
this.numero.toString(),
style: TextStyle(
fontSize: 30.0
),
),
),
);
}
}
I user Flexible widget below
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(flex: 1, child: Caja(Colors.blue, 1, 200.0)),
Flexible(flex: 6, child: Caja(Colors.red, 2, 200.0)),
Caja(Colors.green, 4, 400.0),
],
)
Where does this new leftover space come from?
Can someone explain to me?
I changed the flex value of the second box to 1 - there was no white space. Then to 2 - there was no white space either. From a flex value of 3 upwards, there appears a white space and it gets bigger and bigger.
The documentation states, that a
"..., Flexible does not require the child to fill the available space."
If you examine the source code of the Flexible, the comments say:
"If non-zero, the amount of space the child's can occupy in the main
axis is determined by dividing the free space (after placing the
inflexible children) according to the flex factors of the flexible
children."
I think there might be a problem with the inflexible child - your green box. If you set the flex of your second box so high, you want your first box to be really small. But the flexible children just take the free space up to the inflexible child into consideration and not the free space after it.