Dimensionnement des éléments en pourcentage de largeur / hauteur de l'écran

154

Existe-t-il un moyen simple (non-LayoutBuilder) de dimensionner un élément par rapport à la taille de l'écran (largeur / hauteur)? Par exemple: comment définir la largeur d'un CardView à 65% de la largeur de l'écran.

Cela ne peut pas être fait dans la buildméthode (évidemment), il faudrait donc le différer jusqu'à la post-construction. Y a-t-il un endroit préféré pour mettre une telle logique?

Luke
la source
Juste en disant, ce n'est généralement pas une bonne pratique IMO, c'est des trucs de conception Web. Dans les applications, vous devez généralement utiliser les pixels de l'appareil pour définir les tailles et utiliser les rembourrages pour insérer vos widgets, car votre rapport hauteur / largeur est presque toujours le même (sauf pour les tablettes).
leodriesch
7
Après un an et demi, il semble que ce n'est pas une si mauvaise idée après tout. Chaque mois, de nouveaux téléphones sortent avec des proportions de plus en plus étranges.
Farid

Réponses:

156

FractionallySizedBoxpeut également être utile. Vous pouvez également lire la largeur de l'écran directement à partir de MediaQuery.of(context).sizeet créer une boîte de taille basée sur cela

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

si vous voulez vraiment dimensionner comme une fraction de l'écran quelle que soit la disposition.

Ian Hickson
la source
203

Ceci est une réponse supplémentaire montrant la mise en œuvre de quelques-unes des solutions mentionnées.

FractionallySizedBox

Si vous avez un seul widget, vous pouvez utiliser un FractionallySizedBoxwidget pour spécifier un pourcentage de l'espace disponible à remplir. Ici, le vert Containerest configuré pour remplir 70% de la largeur disponible et 30% de la hauteur disponible.

FractionallySizedBox

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

Étendu

Le Expandedwidget permet à un widget de remplir l'espace disponible, horizontalement s'il est dans une ligne, ou verticalement s'il est dans une colonne. Vous pouvez utiliser la flexpropriété avec plusieurs widgets pour leur donner des pondérations. Ici, le vert Containeroccupe 70% de la largeur et le jaune Container30% de la largeur.

Étendu

Si vous voulez le faire verticalement, remplacez simplement Rowpar Column.

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

Code supplémentaire

Voici le main.dartcode pour votre référence.

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 ...
}
Suragch
la source
4
C'est ainsi que vous écrivez une réponse StackOverflow! Merci! M'a aidé avec mon Dialogstyle :)
Aleksandar
117

Cela pourrait être un peu plus clair:

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

double yourWidth = width * 0.65;

J'espère que cela a résolu votre problème.

Keshav Aditya RP
la source
16

Vous pouvez créer une colonne / ligne avec des enfants flexibles ou étendus qui ont des valeurs flex qui correspondent aux pourcentages souhaités.

Vous pouvez également trouver le widget AspectRatio utile.

Collin Jackson
la source
9
MediaQuery.of(context).size.width
Nitin Mehta
la source
9

Il y a plusieurs façons de faire cela

1. Utilisation de MediaQuery: son retour en plein écran de votre appareil, y compris la barre d'applications, la barre d'outils

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

entrez la description de l'image ici


2. Utilisation de Expanded: vous pouvez définir le rapport largeur / hauteur

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

entrez la description de l'image ici



3. D'autres comme Flexible et AspectRatio et FractionallySizedBox

Sanjayrajsinh
la source
7

vous pouvez utiliser MediaQuery avec le contexte actuel de votre widget et obtenir une largeur ou une hauteur comme celle-ci double width = MediaQuery.of(context).size.width double height = MediaQuery.of(context).size.height après cela, vous pouvez le multiplier par le pourcentage souhaité

parth jansari
la source
7

Obtenez d'abord la taille de l'écran.

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

Après cela, vous pouvez l'obtenir widthet le multiplier avec 0.5pour obtenir 50% de la largeur de l'écran.

double width50 = size.width * 0.5;

Mais le problème survient généralement height, par défaut lorsque nous utilisons

double screenHeight = size.height;

La hauteur que nous obtenons est la hauteur globale qui comprend StatusBar+ notch+ la AppBarhauteur. Ainsi, pour obtenir la hauteur gauche de l'appareil, nous devons soustraire la paddinghauteur ( StatusBar+ notch) et la AppBarhauteur de la hauteur totale. Voici comment nous procédons.

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

Maintenant, nous pouvons utiliser le suivant pour obtenir 50% de notre écran en hauteur.

double height50 = leftHeight * 0.5
CopsOnRoad
la source
3

si vous utilisez GridView, vous pouvez utiliser quelque chose comme la solution d'Ian Hickson.

crossAxisCount: MediaQuery.of(context).size.width <= 400.0 ? 3 : MediaQuery.of(context).size.width >= 1000.0 ? 5 : 4
Rody Davis
la source
2

Utilisez le widget LayoutBuilder qui vous donnera des contraintes que vous pouvez utiliser pour obtenir la hauteur qui exclut l'AppBar et le remplissage. Ensuite, utilisez un SizedBox et fournissez la largeur et la hauteur en utilisant les contraintes du LayoutBuilder

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