Afficher / masquer les widgets dans Flutter par programmation


116

Dans Android, chaque Viewsous-classe a une setVisibility()méthode qui vous permet de modifier la visibilité d'un Viewobjet

Il existe 3 options pour définir la visibilité:

  • Visible: rend le Viewvisible à l'intérieur de la mise en page
  • Invisible: masque le View, mais laisse un espace équivalent à ce Viewqu'il occuperait s'il était visible
  • Gone: masque le Viewet le supprime entièrement de la mise en page. C'est comme si c'était heightet widthc'était0dp

Y a-t-il quelque chose d'équivalent à ce qui précède pour les widgets dans Flutter?

Pour une référence rapide: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

Réponses:


82

MISE À JOUR: Depuis que cette réponse a été écrite, a Visibilityété introduite et fournit la meilleure solution à ce problème.


Vous pouvez utiliser Opacityavec opacity:de 0.0pour dessiner faire un élément caché , mais occupe toujours l' espace.

Pour qu'il n'occupe pas d'espace, remplacez-le par un vide Container().

MODIFIER: pour l'envelopper dans un objet Opacity, procédez comme suit:

            new Opacity(opacity: 0.0, child: new Padding(
              padding: const EdgeInsets.only(
                left: 16.0,
              ),
              child: new Icon(pencil, color: CupertinoColors.activeBlue),
            ))

Tutoriel rapide pour les développeurs Google sur l'opacité: https://youtu.be/9hltevOHQBw


3
Je vous remercie! Ouais, ce n'est pas la manière la plus propre de le faire, mais cela fera certainement l'affaire. Y a-t-il une chance d'avoir une fonctionnalité de visibilité intégrée aux widgets à l'avenir?
user3217522

3
Si le widget réagit normalement à l'entrée de l'utilisateur, assurez-vous de l'envelopper également dans un IgnorePointer, sinon l'utilisateur peut toujours le déclencher.
Duncan Jones

1
Ce n'est pas idéal puisque le widget est toujours là et peut répondre aux tapotements, etc. Voir la réponse ci-dessous en utilisant le widget de visibilité pour la meilleure façon de gérer cela.
Russell Zornes

Comme le disent les commentaires vers le haut, l'utilisation de l'opacité rendra le widget au niveau de renderTree, avec dans certains cas ce n'est pas ce que vous voulez. L'utilisation du widget de visibilité est la plus recommandée.
Isac Moura le

Rendre un widget invisible et avoir l'opacité as0 sont deux choses différentes. Avec un widget invisible, vous pouvez toujours interagir avec lui, c'est juste invisible. Le widget de visibilité vous permet de supprimer le widget jusqu'à ce que vous en ayez besoin.
UndercoverCoder

176

Invisible : le widget prend de l'espace physique sur l'écran mais n'est pas visible par l'utilisateur.

Fini : le widget ne prend pas d'espace physique et a complètement disparu.


Exemple invisible

Visibility(
  child: Text("Invisible"),
  maintainSize: true, 
  maintainAnimation: true,
  maintainState: true,
  visible: false, 
),

Exemple passé

Visibility(
  child: Text("Gone"),
  visible: false,
),

Alternativement, vous pouvez utiliser la ifcondition pour invisible et disparu.

Column(
  children: <Widget>[
    if (show) Text("This can be visible/not depending on condition"),
    Text("This is always visible"),
  ],
) 

17
Cette condition «si» est parfaite!
johnc

I love flutter ❤️
nipunasudha

62

Pour collaborer avec la question et montrer un exemple de remplacement par un vide Container().

Voici l'exemple ci-dessous:

entrez la description de l'image ici

import "package:flutter/material.dart";

void main() {
  runApp(new ControlleApp());
}

class ControlleApp extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "My App",
      home: new HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  HomePageState createState() => new HomePageState();
}

class HomePageState extends State<HomePage> {
  bool visibilityTag = false;
  bool visibilityObs = false;

  void _changed(bool visibility, String field) {
    setState(() {
      if (field == "tag"){
        visibilityTag = visibility;
      }
      if (field == "obs"){
        visibilityObs = visibility;
      }
    });
  }

  @override
  Widget build(BuildContext context){
    return new Scaffold(
      appBar: new AppBar(backgroundColor: new Color(0xFF26C6DA)),
      body: new ListView(
        children: <Widget>[
          new Container(
            margin: new EdgeInsets.all(20.0),
            child: new FlutterLogo(size: 100.0, colors: Colors.blue),
          ),
          new Container(
            margin: new EdgeInsets.only(left: 16.0, right: 16.0),
            child: new Column(
              children: <Widget>[
                visibilityObs ? new Row(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    new Expanded(
                      flex: 11,
                      child: new TextField(
                        maxLines: 1,
                        style: Theme.of(context).textTheme.title,
                        decoration: new InputDecoration(
                          labelText: "Observation",
                          isDense: true
                        ),
                      ),
                    ),
                    new Expanded(
                      flex: 1,
                      child: new IconButton(
                        color: Colors.grey[400],
                        icon: const Icon(Icons.cancel, size: 22.0,),
                        onPressed: () {
                          _changed(false, "obs");
                        },
                      ),
                    ),
                  ],
                ) : new Container(),

                visibilityTag ? new Row(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    new Expanded(
                      flex: 11,
                      child: new TextField(
                        maxLines: 1,
                        style: Theme.of(context).textTheme.title,
                        decoration: new InputDecoration(
                          labelText: "Tags",
                          isDense: true
                        ),
                      ),
                    ),
                    new Expanded(
                      flex: 1,
                      child: new IconButton(
                        color: Colors.grey[400],
                        icon: const Icon(Icons.cancel, size: 22.0,),
                        onPressed: () {
                          _changed(false, "tag");
                        },
                      ),
                    ),
                  ],
                ) : new Container(),
              ],
            )
          ),
          new Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new InkWell(
                onTap: () {
                  visibilityObs ? null : _changed(true, "obs");
                },
                child: new Container(
                  margin: new EdgeInsets.only(top: 16.0),
                  child: new Column(
                    children: <Widget>[
                      new Icon(Icons.comment, color: visibilityObs ? Colors.grey[400] : Colors.grey[600]),
                      new Container(
                        margin: const EdgeInsets.only(top: 8.0),
                        child: new Text(
                          "Observation",
                          style: new TextStyle(
                            fontSize: 12.0,
                            fontWeight: FontWeight.w400,
                            color: visibilityObs ? Colors.grey[400] : Colors.grey[600],
                          ),
                        ),
                      ),
                    ],
                  ),
                )
              ),
              new SizedBox(width: 24.0),
              new InkWell(
                onTap: () {
                  visibilityTag ? null : _changed(true, "tag");
                },
                child: new Container(
                  margin: new EdgeInsets.only(top: 16.0),
                  child: new Column(
                    children: <Widget>[
                      new Icon(Icons.local_offer, color: visibilityTag ? Colors.grey[400] : Colors.grey[600]),
                      new Container(
                        margin: const EdgeInsets.only(top: 8.0),
                        child: new Text(
                          "Tags",
                          style: new TextStyle(
                            fontSize: 12.0,
                            fontWeight: FontWeight.w400,
                            color: visibilityTag ? Colors.grey[400] : Colors.grey[600],
                          ),
                        ),
                      ),
                    ],
                  ),
                )
              ),
            ],
          )                    
        ],
      )
    );
  }
}

5
Cela devrait être la réponse acceptée. C'est l'implémentation correcte de "afficher / masquer les widgets par programme"
Bishwajyoti Roy

Oui, cela devrait certainement être accepté car cela utilise un pilier de base de Flutter, c'est-à-dire setState () ... sinon, comment allez-vous aller et venir entre Visible / InVisible dans votre widget Stateful!?.
Yo Apps le

27

Flutter contient maintenant un widget de visibilité que vous devez utiliser pour afficher / masquer les widgets. Le widget peut également être utilisé pour basculer entre 2 widgets en modifiant le remplacement.

Ce widget peut atteindre n'importe lequel des états visibles, invisibles, partis et bien plus encore.

    Visibility(
      visible: true //Default is true,
      child: Text('Ndini uya uya'),
      //maintainSize: bool. When true this is equivalent to invisible;
      //replacement: Widget. Defaults to Sizedbox.shrink, 0x0
    ),

19

Essayez le Offstagewidget

si l'attribut offstage:truen'occupe pas l'espace physique et invisible,

si attribut offstage:falseil occupera l'espace physique et visible

Offstage(
   offstage: true,
   child: Text("Visible"),
),

Remarque à ce sujet: l' état Flutter docs , "Offstage peut être utilisé pour mesurer les dimensions d'un widget sans l'afficher (encore) à l'écran. Pour masquer un widget de la vue alors qu'il n'est pas nécessaire, préférez supprimer complètement le widget de l'arborescence. plutôt que de le maintenir vivant dans un sous-arbre Offstage. ".
lukeic

10
bool _visible = false;

 void _toggle() {
    setState(() {
      _visible = !_visible;
    });
  }

onPressed: _toggle,

Visibility(
            visible:_visible,
            child: new Container(
            child: new  Container(
              padding: EdgeInsets.fromLTRB(15.0, 0.0, 15.0, 10.0),
              child: new Material(
                elevation: 10.0,
                borderRadius: BorderRadius.circular(25.0),
                child: new ListTile(
                  leading: new Icon(Icons.search),
                  title: new TextField(
                    controller: controller,
                    decoration: new InputDecoration(
                        hintText: 'Search for brands and products', border: InputBorder.none,),
                    onChanged: onSearchTextChanged,
                  ),
                  trailing: new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
                    controller.clear();
                    onSearchTextChanged('');
                  },),
                ),
              ),
            ),
          ),
          ),

9

Dans Flutter 1.5 et Dart 2.3 pour la visibilité disparue, vous pouvez définir la visibilité en utilisant une instruction if dans la collection sans avoir à utiliser de conteneurs.

par exemple

child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
              Text('This is text one'),
              if (_isVisible) Text('can be hidden or shown'), // no dummy container/ternary needed
              Text('This is another text'),
              RaisedButton(child: Text('show/hide'), onPressed: (){
                  setState(() {
                    _isVisible = !_isVisible; 
                  });
              },)

          ],
        )

C'est tellement mieux que les options disponibles dans la version précédente de flutter / dart.Merci!
Hammer

8

Vous pouvez encapsuler n'importe quel widget dans votre code avec un nouveau widget appelé (Visibilité), c'est à partir de la lampe jaune à l'extrême gauche du widget que vous voulez qu'il soit visible

exemple: disons que vous voulez rendre une ligne invisible:

  1. Cliquez dans la lampe et choisissez (Wrap with widget)
  2. Renommez le widget en visibilité
  3. Ajoutez la propriété visible et définissez-la sur false
  4. L'enfant du widget nouvellement créé (widget de visibilité) est le widget dont vous voulez qu'il soit invisible

              Visibility(
                  visible: false,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      SizedBox(
                        width: 10,
                      ),
                      Text("Search",
                        style: TextStyle(fontSize: 20
                        ),),
                    ],
                  ),
                ),

J'espère que cela aidera quelqu'un dans le futur


5

Pour les débutants, essayez ceci aussi.

class Visibility extends StatefulWidget {
  @override
  _VisibilityState createState() => _VisibilityState();
}

class _VisibilityState extends State<Visibility> {
  bool a = true;
  String mText = "Press to hide";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Visibility",
      home: new Scaffold(
          body: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new RaisedButton(
                onPressed: _visibilitymethod, child: new Text(mText),),
                a == true ? new Container(
                width: 300.0,
                height: 300.0,
                color: Colors.red,
              ) : new Container(),
            ],
          )
      ),
    );
  }

  void _visibilitymethod() {
    setState(() {
      if (a) {
        a = false;
        mText = "Press to show";
      } else {
        a = true;
        mText = "Press to hide";
      }
    });
  }
}

3

Mettre à jour

Flutter a maintenant un widget de visibilité . Pour implémenter votre propre solution, commencez par le code ci-dessous.


Créez vous-même un widget.

afficher / masquer

class ShowWhen extends StatelessWidget {
  final Widget child;
  final bool condition;
  ShowWhen({this.child, this.condition});

  @override
  Widget build(BuildContext context) {
    return Opacity(opacity: this.condition ? 1.0 : 0.0, child: this.child);
  }
}

afficher / supprimer

class RenderWhen extends StatelessWidget {
  final Widget child;
  final bool condition;
  RenderWhen({this.child, this.show});

  @override
  Widget build(BuildContext context) {
    return this.condition ? this.child : Container();
  }
}

Au fait, est-ce que quelqu'un a un meilleur nom pour les widgets ci-dessus?


Plus de lectures

  1. Article sur la création d'un widget de visibilité.

3

Comme déjà souligné par @CopsOnRoad, vous pouvez utiliser le widget Visibilité. Mais, si vous souhaitez conserver son état, par exemple, si vous souhaitez créer un visualiseur et faire apparaître et disparaître un certain bouton en fonction de la page, vous pouvez le faire de cette façon

void checkVisibilityButton() {
  setState(() {
  isVisibileNextBtn = indexPage + 1 < pages.length;
  });
}    

 Stack(children: <Widget>[
      PageView.builder(
        itemCount: pages.length,
        onPageChanged: (index) {
          indexPage = index;
          checkVisibilityButton();
        },
        itemBuilder: (context, index) {
          return pages[index];
        },
        controller: controller,
      ),
      Container(
        alignment: Alignment.bottomCenter,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Visibility(
              visible: isVisibileNextBtn == true ? true : false,
              child: "your widget"
            )
          ],
        ),
      )
    ]))

0

Peut-être que vous pouvez utiliser la fonction Navigator comme ceci Navigator.of(context).pop();


-8

Une solution consiste à définir la propriété de couleur du widget sur Colors.transparent. Par exemple:

IconButton(
    icon: Image.asset("myImage.png",
        color: Colors.transparent,
    ),
    onPressed: () {},
),

1
Pas une bonne solution car le transparent IconButtonreçoit toujours un clic et occupe de l'espace. Veuillez modifier ou supprimer cette réponse avant que les gens ne la votent contre.
CopsOnRoad le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.