Dimensionar elementos al porcentaje de ancho / alto de pantalla


154

¿Existe una forma simple (no LayoutBuilder) de dimensionar un elemento en relación con el tamaño de la pantalla (ancho / alto)? Por ejemplo: ¿cómo configuro el ancho de un CardView para que sea el 65% del ancho de la pantalla?

No se puede hacer dentro del buildmétodo (obviamente), por lo que tendría que diferirse hasta la construcción posterior. ¿Hay un lugar preferido para poner lógica como esta?


Solo digo, esto generalmente no es una buena práctica IMO, eso es material de diseño web. En las aplicaciones, generalmente debe usar píxeles del dispositivo para definir tamaños y usar Rellenos para insertar sus widgets, ya que su relación de aspecto es casi siempre la misma (excepto para tabletas).
leodriesch

77
Después de otros 1,5 años, parece que esta no es una mala idea después de todo. Cada mes salen nuevos teléfonos con una relación de aspecto más extraña y extraña.
Farid

Respuestas:


156

FractionallySizedBoxTambién puede ser útil. También puede leer el ancho de la pantalla directamente MediaQuery.of(context).sizey crear un cuadro de tamaño basado en eso

MediaQuery.of(context).size.width * 0.65

si realmente desea dimensionar como una fracción de la pantalla, independientemente de cuál sea el diseño.


203

Esta es una respuesta complementaria que muestra la implementación de un par de las soluciones mencionadas.

FractionallySizedBox

Si tiene un único widget, puede usar un FractionallySizedBoxwidget para especificar un porcentaje del espacio disponible para llenar. Aquí el verde Containerestá configurado para llenar el 70% del ancho disponible y el 30% de la altura disponible.

FractionallySizedBox

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

Expandido

El Expandedwidget permite que un widget llene el espacio disponible, horizontalmente si está en una fila, o verticalmente si está en una columna. Puede usar la flexpropiedad con múltiples widgets para darles peso. Aquí el verde Containertoma el 70% del ancho y el amarillo Containertoma el 30% del ancho.

Expandido

Si desea hacerlo verticalmente, simplemente reemplácelo Rowcon Column.

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

Código suplementario

Aquí está el main.dartcódigo para su referencia.

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 ...
}

44
¡Así es como escribes una respuesta de StackOverflow! ¡Gracias! Me ayudó con mi Dialogestilo :)
Aleksandar

117

Esto podría ser un poco más claro:

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

double yourWidth = width * 0.65;

Espero que esto haya resuelto tu problema.




9

Hay muchas maneras de hacer esto.

1. Uso de MediaQuery: devuelve la pantalla completa de su dispositivo, incluida la barra de aplicaciones, la barra de herramientas

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

ingrese la descripción de la imagen aquí


2. Usando expandido: puede establecer el ancho / alto en relación

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

ingrese la descripción de la imagen aquí



3. A otros les gusta Flexible y AspectRatio y FractionallySizedBox


7

puede usar MediaQuery con el contexto actual de su widget y obtener un ancho o alto como este double width = MediaQuery.of(context).size.width double height = MediaQuery.of(context).size.height después de eso, puede multiplicarlo con el porcentaje que desee


7

Primero obtenga el tamaño de la pantalla.

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

Después de esto, puede obtener widthy multiplicarlo 0.5para obtener el 50% del ancho de la pantalla.

double width50 = size.width * 0.5;

Pero el problema generalmente viene height, por defecto cuando usamos

double screenHeight = size.height;

La altura que obtenemos es la altura global que incluye StatusBar+ notch+ AppBaraltura. Entonces, para obtener la altura izquierda del dispositivo, necesitamos restar la paddingaltura ( StatusBar+ notch) y la AppBaraltura de la altura total. Así es como lo hacemos.

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

Ahora podemos usar el siguiente para obtener el 50% de nuestra pantalla en altura.

double height50 = leftHeight * 0.5

3

Si está utilizando GridView, puede usar algo como la solución de Ian Hickson.

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

2

Use el widget LayoutBuilder que le dará restricciones que puede usar para obtener la altura que excluye la barra de aplicaciones y el relleno. Luego use un SizedBox y proporcione el ancho y la altura usando las restricciones del LayoutBuilder

return LayoutBuilder(builder: (context2, constraints) {
  return Column(
    children: <Widget>[
      SizedBox(
        width: constraints.maxWidth,
        height: constraints.maxHeight,
        ...
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.