Mostrar / ocultar widgets en Flutter mediante programación


116

En Android, cada Viewsubclase tiene un setVisibility()método que le permite modificar la visibilidad de un Viewobjeto

Hay 3 opciones para configurar la visibilidad:

  • Visible: renderiza lo Viewvisible dentro del diseño.
  • Invisible: Oculta el View, pero deja un espacio equivalente al que Viewocuparía si fuera visible.
  • Desaparecido: oculta Viewy elimina por completo del diseño. Es como si fuera heighty widthfuera0dp

¿Existe algo equivalente a lo anterior para los widgets en Flutter?

Para una referencia rápida: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

Respuestas:


82

ACTUALIZACIÓN: Desde que se escribió esta respuesta, Visibilityse introdujo y proporciona la mejor solución a este problema.


Puede usar Opacitycon una opacity:de 0.0para dibujar hacer que un elemento esté oculto pero que aún ocupe espacio.

Para que no ocupe espacio, reemplácelo con un vacío Container().

EDITAR: Para envolverlo en un objeto Opacity, haga lo siguiente:

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

Tutorial rápido para desarrolladores de Google sobre opacidad: https://youtu.be/9hltevOHQBw


3
¡Gracias! Sí, esa no es la forma más limpia de hacerlo, pero definitivamente cumplirá el propósito. ¿Alguna posibilidad de tener una funcionalidad de visibilidad integrada con widgets en el futuro?
user3217522

3
Si el widget normalmente reacciona a la entrada del usuario, asegúrese de envolverlo IgnorePointertambién, de lo contrario, el usuario aún puede activarlo.
Duncan Jones

1
Esto no es ideal ya que el widget todavía está allí y puede responder a los toques, etc. Consulte la respuesta a continuación utilizando el widget de visibilidad para conocer la mejor manera de manejar esto.
Russell Zornes

Como dicen los comentarios hacia arriba, el uso de opacidad renderizará el widget en renderTree, y en algunos casos no es lo que desea. Se recomienda utilizar el widget de visibilidad.
Isac Moura

Hacer invisible un widget y tener una opacidad as0 son dos cosas diferentes. Con un widget invisible, aún puede interactuar con él, simplemente es invisible. El widget de visibilidad le permite eliminar el widget hasta que lo necesite.
UndercoverCoder

176

Invisible : el widget ocupa espacio físico en la pantalla pero no es visible para el usuario.

Desaparecido : el widget no ocupa ningún espacio físico y desapareció por completo.


Ejemplo invisible

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

Ido ejemplo

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

Alternativamente, puede usar ifcondición para invisible y desaparecido.

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

17
¡Esa condición 'si' es perfecta!
johnc

Me encanta flutter ❤️
nipunasudha

62

Colaborar con la pregunta y mostrar un ejemplo de cómo reemplazarla con un vacío Container().

Este es el ejemplo siguiente:

ingrese la descripción de la imagen aquí

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
Esta debería ser la respuesta aceptada. Esta es la implementación correcta de "mostrar / ocultar widgets mediante programación"
Bishwajyoti Roy

Sí, esto definitivamente debería ser aceptado porque utiliza un pilar fundamental de Flutter, es decir, setState () ... de lo contrario, ¿de qué otra manera vas a ir y venir entre Visible / InVisible en tu widget con estado?
Yo Apps

27

Flutter ahora contiene un widget de visibilidad que debes usar para mostrar / ocultar widgets. El widget también se puede utilizar para cambiar entre 2 widgets cambiando el reemplazo.

Este widget puede lograr cualquiera de los estados visible, invisible, desaparecido y mucho más.

    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

Prueba el Offstagewidget

si el atributo offstage:trueno ocupa el espacio físico e invisible,

si atributo offstage:falseocupará el espacio físico y visible

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

Tenga en cuenta esto: el estado de los documentos de Flutter , "Offstage se puede usar para medir las dimensiones de un widget sin mostrarlo en la pantalla (todavía). Para ocultar un widget de la vista cuando no es necesario, prefiera eliminar el widget del árbol por completo en lugar de mantenerlo vivo en un subárbol fuera del escenario ".
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

En flutter 1.5 y Dart 2.3 para la visibilidad perdida, puede establecer la visibilidad utilizando una declaración if dentro de la colección sin tener que hacer uso de contenedores.

p.ej

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; 
                  });
              },)

          ],
        )

Eso es mucho mejor que las opciones disponibles en la versión anterior de flutter / dardo. ¡Gracias!
Martillo

8

Puede encapsular cualquier widget en su código con un nuevo widget llamado (Visibilidad), esto es desde la lámpara amarilla en el lado izquierdo del widget que desea que esté invisible

ejemplo: digamos que quiere hacer una fila invisible:

  1. Haga clic en la lámpara y elija (Envolver con widget)
  2. Cambiar el nombre del widget a Visibilidad
  3. Agregue la propiedad visible y establézcala en falso
  4. El elemento secundario del widget recién creado (widget de visibilidad) es el widget que desea que sea invisible

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

Espero que ayude a alguien en el futuro


5

Para principiantes, pruebe esto también.

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

Actualizar

Flutter ahora tiene un widget de visibilidad . Para implementar su propia solución, comience con el siguiente código.


Haz un widget tú mismo.

mostrar ocultar

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);
  }
}

mostrar / eliminar

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();
  }
}

Por cierto, ¿alguien tiene un mejor nombre para los widgets anteriores?


Más lecturas

  1. Artículo sobre cómo hacer un widget de visibilidad.

3

Como ya lo destacó @CopsOnRoad, puede usar el widget Visibilidad. Pero, si desea mantener su estado, por ejemplo, si desea construir un visor y hacer que un determinado botón aparezca y desaparezca en función de la página, puede hacerlo de esta manera.

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


-8

Una solución es establecer esta propiedad de color del widget en Colors.transparent. Por ejemplo:

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

1
No es una buena solución porque el transparente IconButtontodavía recibe clic y ocupa espacio. Por favor, edite o elimine esta respuesta antes de que la gente la rechace.
CopsOnRoad
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.