208 votes

Comment obtenir la hauteur d'un Widget ?

Je ne comprends pas comment LayoutBuilder est utilisé pour obtenir la hauteur d'un Widget.

J'ai besoin d'afficher la liste des widgets et d'obtenir leur hauteur afin de pouvoir calculer certains effets de défilement spéciaux. Je développe un paquet et d'autres développeurs fournissent des widgets (je ne les contrôle pas). J'ai lu que LayoutBuilder peut être utilisé pour obtenir la hauteur.

Dans un cas très simple, j'ai essayé d'envelopper le widget dans LayoutBuilder.builder et de le placer dans la pile, mais j'obtiens toujours les résultats suivants minHeight 0.0 et maxHeight INFINITY . Est-ce que j'utilise mal le LayoutBuilder ?

EDIT : Il semble que LayoutBuilder soit un échec. J'ai trouvé le CustomSingleChildLayout ce qui est presque une solution.

J'ai étendu ce délégué, et j'ai pu obtenir la hauteur du widget en getPositionForChild(Size size, Size childSize) méthode. MAIS, la première méthode qui est appelée est Size getSize(BoxConstraints constraints) et comme contraintes, j'obtiens 0 à INFINITY parce que je pose ces CustomSingleChildLayouts dans une ListView.

Mon problème est que SingleChildLayoutDelegate getSize fonctionne comme si elle avait besoin de retourner la hauteur d'une vue. Je ne connais pas la hauteur d'un enfant à ce moment-là. Je ne peux que renvoyer constraints.smallest (qui est 0, la hauteur est 0), ou constraints.biggest qui est infini et fait planter l'application.

Dans les docs, il est même dit :

...mais la taille du parent ne peut pas dépendre de la taille de l'enfant.

Et c'est une limitation bizarre.

1 votes

LayoutBuilder vous donnera les contraintes de boîte du parent. Si vous voulez les tailles des enfants, vous devez utiliser une stratégie différente. Un exemple que je peux citer est le widget Wrap, qui effectue la mise en page en fonction de la taille de ses enfants dans la classe RenderWrap associée. Mais cela se produit pendant la mise en page, et non pendant la fonction build().

0 votes

@JonahWilliams Hmm. Je ne vois pas comment Wrap peut m'aider puisque c'est un widget conçu pour disposer les enfants autour (fonctionne quelque chose comme la grille flexbox du web). J'ai un widget enfant dont j'ai besoin de trouver la hauteur. Veuillez voir l'édition dans la question. J'ai presque résolu le problème avec CustomSingleChildLayout mais je suis resté bloqué sur ses limites.

0 votes

Pouvez-vous expliquer plus précisément ce que vous voulez ? Il existe de multiples solutions. Mais chacune a des cas d'utilisation différents.

6voto

Gan Quan Points 31

Si je comprends bien, vous voulez mesurer la dimension de certains widgets arbitraires, et vous pouvez envelopper ces widgets avec un autre widget. Dans ce cas, la méthode dans le cette réponse devrait fonctionner pour vous.

La solution consiste à lier une fonction de rappel dans le cycle de vie du widget, qui sera appelée après le rendu de la première image. context.size . Le problème est que vous devez envelopper le widget que vous voulez mesurer dans un widget à état. Et, si vous avez absolument besoin de la taille dans build() alors vous ne pouvez y accéder que dans le deuxième rendu (il n'est disponible qu'après le premier rendu).

1 votes

Merci pour la remarque, jetez un coup d'œil à ma solution complète. stackoverflow.com/a/60868972/7061265

5voto

jitesh mohite Points 3119

findRenderObject() renvoie le RenderBox qui est utilisé pour donner la taille du widget dessiné et qui doit être appelé après la construction de l'arbre des widgets, il doit donc être utilisé avec un mécanisme de rappel ou avec la fonction addPostFrameCallback() les rappels.

class SizeWidget extends StatefulWidget {
  @override
  _SizeWidgetState createState() => _SizeWidgetState();
}

class _SizeWidgetState extends State<SizeWidget> {
  final GlobalKey _textKey = GlobalKey();
  Size textSize;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => getSizeAndPosition());
  }

  getSizeAndPosition() {
    RenderBox _cardBox = _textKey.currentContext.findRenderObject();
    textSize = _cardBox.size;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Size Position"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Text(
            "Currern Size of Text",
            key: _textKey,
            textAlign: TextAlign.center,
            style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
          ),
          SizedBox(
            height: 20,
          ),
          Text(
            "Size - $textSize",
            textAlign: TextAlign.center,
          ),
        ],
      ),
    );
  }
}

Sortie :

enter image description here

2voto

Kalpesh Khandla Points 51

Il n'y a pas de moyen direct de calculer la taille du widget, donc pour trouver cela nous devons prendre l'aide du contexte du widget.

L'appel de context.size nous renvoie l'objet Size, qui contient la hauteur et la largeur du widget. context.size calcule la boîte de rendu d'un widget et renvoie la taille.

Checkout https://medium.com/flutterworld/flutter-how-to-get-the-height-of-the-widget-be4892abb1a2

2voto

Anup Gupta Points 578

Peut-être que ceci pourrait aider

Testé sur Flutter : 2.2.3

Copiez le code ci-dessous dans votre projet.

 import 'package:flutter/material.dart';
    import 'package:flutter/scheduler.dart';

    class WidgetSize extends StatefulWidget {
      final Widget child;
      final Function onChange;

      const WidgetSize({
        Key? key,
        required this.onChange,
        required this.child,
      }) : super(key: key);

      @override
      _WidgetSizeState createState() => _WidgetSizeState();
    }

    class _WidgetSizeState extends State<WidgetSize> {
      @override
      Widget build(BuildContext context) {
        SchedulerBinding.instance!.addPostFrameCallback(postFrameCallback);
        return Container(
          key: widgetKey,
          child: widget.child,
        );
      }

      var widgetKey = GlobalKey();
      var oldSize;

      void postFrameCallback(_) {
        var context = widgetKey.currentContext;
        if (context == null) return;

        var newSize = context.size;
        if (oldSize == newSize) return;

        oldSize = newSize;
        widget.onChange(newSize);
      }
    }

déclarer une variable pour stocker Taille

Size mySize = Size.zero;

Ajoutez le code suivant pour obtenir la taille :

 child: WidgetSize(
          onChange: (Size mapSize) {
            setState(() {
              mySize = mapSize;
               print("mySize:" + mySize.toString());
             });
             },
         child: ()

1voto

Ayham Orfali Points 1

Le moyen le plus simple est d'utiliser Taille mesurée c'est un widget qui calcule la taille de son enfant en cours d'exécution.

Vous pouvez l'utiliser comme ça :

MeasuredSize(
          onChange: (Size size) {
            setState(() {
              print(size);
            });
          },
          child: Text(
            '$_counter',
            style: Theme.of(context).textTheme.headline4,
          ),
        );

Vous pouvez le trouver ici : https://pub.dev/packages/measured_size

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X