[flutter] Sizing elements to percentage of screen width/height

Is there a simple (non-LayoutBuilder) way to size an element relative to screen size (width/height)? For example: how do I set the width of a CardView to be 65% of the screen width.

It can't be done inside the build method (obviously) so it would have to be deferred until post build. Is there a preferred place to put logic like this?

This question is related to flutter

The answer is


you can use MediaQuery with the current context of your widget and get width or height like this double width = MediaQuery.of(context).size.width double height = MediaQuery.of(context).size.height after that, you can multiply it with the percentage you want


if you are using GridView you can use something like Ian Hickson's solution.

crossAxisCount: MediaQuery.of(context).size.width <= 400.0 ? 3 : MediaQuery.of(context).size.width >= 1000.0 ? 5 : 4

MediaQuery.of(context).size.width

Use the LayoutBuilder Widget that will give you constraints that you can use to obtain the height that excludes the AppBar and the padding. Then use a SizedBox and provide the width and height using the constraints from the LayoutBuilder

return LayoutBuilder(builder: (context2, constraints) {
  return Column(
    children: <Widget>[
      SizedBox(
        width: constraints.maxWidth,
        height: constraints.maxHeight,
        ...

You could build a Column/Row with Flexible or Expanded children that have flex values that add up to the percentages you want.

You may also find the AspectRatio widget useful.


Code :

MediaQuery.of(context).size.width //to get the width of screen
MediaQuery.of(context).size.height //to get height of screen

There is many way to do this.

1. Using MediaQuery : Its return fullscreen of your device including appbar,toolbar

 Container(
        width: MediaQuery.of(context).size.width * 0.50,
        height: MediaQuery.of(context).size.height*0.50, 
        color: Colors.blueAccent[400],
 )

enter image description here


2. Using Expanded : You can set width/height in ratio

 Container(
        height: MediaQuery.of(context).size.height * 0.50,
        child: Row(
          children: <Widget>[
            Expanded(
              flex: 70,
              child: Container(
                color: Colors.lightBlue[400],
              ),
            ),
            Expanded(
              flex: 30,
              child: Container(
                color: Colors.deepPurple[800],
              ),
            )
          ],
        ),
    )

enter image description here



3. Others Like Flexible and AspectRatio and FractionallySizedBox


This is a supplemental answer showing the implementation of a couple of the solutions mentioned.

FractionallySizedBox

If you have a single widget you can use a FractionallySizedBox widget to specify a percentage of the available space to fill. Here the green Container is set to fill 70% of the available width and 30% of the available height.

FractionallySizedBox
Widget myWidget() {
  return FractionallySizedBox(
    widthFactor: 0.7,
    heightFactor: 0.3,
    child: Container(
      color: Colors.green,
    ),
  );
}

Expanded

The Expanded widget allows a widget to fill the available space, horizontally if it is in a row, or vertically if it is in a column. You can use the flex property with multiple widgets to give them weights. Here the green Container takes 70% of the width and the yellow Container takes 30% of the width.

Expanded

If you want to do it vertically, then just replace Row with Column.

Widget myWidget() {
  return Row(
    children: <Widget>[
      Expanded(
        flex: 7,
        child: Container(
          color: Colors.green,
        ),
      ),
      Expanded(
        flex: 3,
        child: Container(
          color: Colors.yellow,
        ),
      ),
    ],
  );
}

Supplemental code

Here is the main.dart code for your reference.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("FractionallySizedBox"),
        ),
        body: myWidget(),
      ),
    );
  }
}

// replace with example code above
Widget myWidget() {
  return ...
}

There are several possibilities:

1- The first one is the use of the MediaQuery :

Code :

MediaQuery.of(context).size.width //to get the width of screen
MediaQuery.of(context).size.height //to get height of screen

Example of use :

Container(
        color: Colors.yellow,
        height: MediaQuery.of(context).size.height * 0.65,
        width: MediaQuery.of(context).size.width,
      )

Output :

enter image description here

2- The use of FractionallySizedBox

Creates a widget that sizes its child to a fraction of the total available space.

Example :

FractionallySizedBox(
           widthFactor: 0.65, // between 0 and 1 
           heightFactor: 1.0,
           child:Container(color: Colors.red
           ,),
         )

Output :

enter image description here

3- The use of other widgets such as Expanded , Flexible and AspectRatio and more .


This might be a little more clear:

double width = MediaQuery.of(context).size.width;

double yourWidth = width * 0.65;

Hope this solved your problem.


First get the size of screen.

Size size = MediaQuery.of(context).size;

After this you can get width and multiply it with 0.5 to get 50% of screen width.

double width50 = size.width * 0.5;

But problem generally comes in height, by default when we use

double screenHeight = size.height;

The height we get is global height which includes StatusBar + notch + AppBar height. So, in order to get the left height of the device, we need to subtract padding height (StatusBar + notch) and AppBar height from total height. Here is how we do it.

double abovePadding = MediaQuery.of(context).padding.top;
double appBarHeight = appBar.preferredSize.height;
double leftHeight = screenHeight - abovePadding - appBarHeight;

Now we can use following to get 50% of our screen in height.

double height50 = leftHeight * 0.5