Mostra / nascondi i widget in Flutter a livello di programmazione


112

In Android, ogni singola Viewsottoclasse ha un setVisibility()metodo che consente di modificare la visibilità di un Viewoggetto

Sono disponibili 3 opzioni per impostare la visibilità:

  • Visibile: rende Viewvisibile all'interno del layout
  • Invisibile: nasconde il View, ma lascia uno spazio che è equivalente a quello Viewche occuperebbe se fosse visibile
  • Andato: nasconde il Viewe lo rimuove completamente dal layout. È come se fosse heighte widthfosse0dp

C'è qualcosa di equivalente a quanto sopra per i widget in Flutter?

Per una rapida consultazione: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

Risposte:


81

AGGIORNAMENTO: poiché questa risposta è stata scritta, è Visibilitystata introdotta e fornisce la migliore soluzione a questo problema.


È possibile utilizzare Opacitycon una opacity:di 0.0disegnare rendere un elemento nascosto, ma ancora occupano spazio.

Per evitare che occupi spazio, sostituiscilo con uno vuoto Container().

MODIFICA: per avvolgerlo in un oggetto Opacity, procedi come segue:

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

Tutorial rapido per sviluppatori Google su Opacity: https://youtu.be/9hltevOHQBw


3
Grazie! Sì, non è il modo più pulito per farlo, ma sicuramente servirà allo scopo. C'è qualche possibilità di avere una funzionalità di visibilità integrata con i widget in futuro?
user3217522

3
Se il widget normalmente reagisce all'input dell'utente, assicurati di racchiuderlo anche in un IgnorePointer, altrimenti l'utente può comunque attivarlo.
Duncan Jones

1
Questo non è l'ideale poiché il widget è ancora lì e può rispondere ai tocchi, ecc. Vedere la risposta di seguito utilizzando il widget Visibilità per il modo migliore per gestirlo.
Russell Zornes,

Come dicono i commenti in alto, l'uso dell'opacità renderà il Widget nel renderTree, con in alcuni casi non è quello che vuoi. Si consiglia di utilizzare il widget di visibilità.
Isac Moura

Rendere invisibile un widget e avere opacità as0 sono due cose diverse. Con un widget invisibile, puoi comunque interagire con esso, è semplicemente invisibile. Il widget di visibilità consente di rimuovere il widget fino a quando non è necessario.
UndercoverCoder

173

Invisibile : il widget occupa spazio fisico sullo schermo ma non è visibile all'utente.

Andato : il widget non occupa spazio fisico ed è completamente sparito.


Esempio invisibile

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

Andato esempio

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

In alternativa, puoi usare la ifcondizione sia per invisibile che per scomparso.

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

16
Quella condizione "se" è perfetta!
johnc

I love flutter ❤️
nipunasudha

62

Per collaborare con la domanda e mostrare un esempio di sostituzione con un vuoto Container().

Di seguito è riportato l'esempio:

inserisci qui la descrizione dell'immagine

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
Questa dovrebbe essere la risposta accettata. Questa è la corretta implementazione di "mostra / nascondi widget in modo programmatico"
Bishwajyoti Roy

Sì, questo dovrebbe essere sicuramente accettato perché utilizza un pilastro fondamentale di Flutter, cioè setState () ... altrimenti in quale altro modo andrai avanti e indietro tra Visible / InVisible nel tuo widget Stateful!?.
Yo Apps

27

Flutter ora contiene un widget di visibilità che dovresti usare per mostrare / nascondere i widget. Il widget può anche essere utilizzato per passare da un widget all'altro cambiando la sostituzione.

Questo widget può raggiungere qualsiasi stato visibile, invisibile, scomparso e molto altro ancora.

    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

Prova il Offstagewidget

se l'attributo offstage:truenon occupa lo spazio fisico e invisibile,

se attributo offstage:falseoccuperà lo spazio fisico e visibile

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

Nota su questo: la documentazione di Flutter dichiara, "Fuori scena può essere utilizzato per misurare le dimensioni di un widget senza portarlo sullo schermo (ancora). Per nascondere un widget alla vista mentre non è necessario, preferisci rimuovere completamente il widget dall'albero piuttosto che tenerlo vivo in una sottostruttura 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

In flutter 1.5 e Dart 2.3 per la visibilità scomparsa, puoi impostare la visibilità utilizzando un'istruzione if all'interno della raccolta senza dover utilizzare i contenitori.

per esempio

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

          ],
        )

È molto meglio delle opzioni disponibili nella versione precedente di flutter / dart. Grazie!
Martello

8

Puoi incapsulare qualsiasi widget nel tuo codice con un nuovo widget chiamato (Visibility), questo è dalla spia gialla sul lato sinistro del widget che vuoi che sia invisibile

esempio: supponi di voler rendere invisibile una riga:

  1. Fare clic sulla lampada e scegliere (Avvolgi con widget)
  2. Rinomina il widget in Visibilità
  3. Aggiungi la proprietà visible e impostala su false
  4. Il Figlio del widget appena creato (Visibility Widget) è il Widget che vuoi che sia invisibile

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

Spero che possa aiutare qualcuno in futuro


5

Per i principianti prova anche questo.

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

Aggiornare

Flutter ora ha un widget Visibilità . Per implementare la tua soluzione, inizia con il codice seguente.


Crea tu stesso un widget.

mostra nascondi

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

mostra / rimuovi

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

A proposito, qualcuno ha un nome migliore per i widget sopra?


Altre letture

  1. Articolo su come creare un widget di visibilità.

3

Come già evidenziato da @CopsOnRoad, puoi utilizzare il widget Visibility. Ma, se vuoi mantenere il suo stato, ad esempio, se vuoi creare un viewpager e far apparire e scomparire un determinato pulsante in base alla pagina, puoi farlo in questo modo

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

Forse puoi usare la funzione Navigator in questo modo Navigator.of(context).pop();


-8

Una soluzione è impostare la proprietà color del widget su Colors.transparent. Per esempio:

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

1
Non è una buona soluzione perché il trasparente IconButtonriceve ancora clic e occupa spazio. Si prega di modificare o eliminare questa risposta prima che le persone la votino negativamente.
CopsOnRoad
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.