Widgets in Flutter programmgesteuert ein- / ausblenden

110

In Android verfügt jede einzelne ViewUnterklasse über eine setVisibility()Methode, mit der Sie die Sichtbarkeit eines ViewObjekts ändern können

Es gibt 3 Möglichkeiten, die Sichtbarkeit einzustellen:

  • Sichtbar: Macht das ViewSichtbare im Layout sichtbar
  • Unsichtbar: Blendet das aus View, hinterlässt aber eine Lücke, die dem entspricht, was das Vieweinnehmen würde, wenn es sichtbar wäre
  • Vorbei: Blendet das aus Viewund entfernt es vollständig aus dem Layout. Es ist , als ob sein heightund widthwaren0dp

Gibt es etwas Äquivalentes zu Widgets in Flutter?

Für eine kurze Referenz: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

user3217522
quelle

Antworten:

81

UPDATE: Da diese Antwort geschrieben wurde, Visibilitywurde sie eingeführt und bietet die beste Lösung für dieses Problem.


Sie können Opacitymit einem opacity:von verwenden 0.0, um ein Element zu zeichnen, das versteckt ist, aber dennoch Platz einnimmt.

Ersetzen Sie es durch ein leeres, damit es keinen Platz einnimmt Container().

BEARBEITEN: Gehen Sie wie folgt vor, um es in ein Deckkraftobjekt zu verpacken:

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

Kurzanleitung für Google-Entwickler zur Deckkraft: https://youtu.be/9hltevOHQBw

Collin Jackson
quelle
3
Danke dir! Ja, das ist nicht die sauberste Art, aber es wird definitiv den Zweck erfüllen. Gibt es eine Chance, dass in Zukunft eine Sichtbarkeitsfunktion in Widgets integriert wird?
user3217522
3
Wenn das Widget normalerweise auf Benutzereingaben reagiert, müssen Sie es ebenfalls in eine IgnorePointereinbinden, da der Benutzer es sonst weiterhin auslösen kann.
Duncan Jones
1
Dies ist nicht ideal, da das Widget noch vorhanden ist und auf Tippen usw. reagieren kann. Die beste Möglichkeit, dies zu handhaben, finden Sie in der Antwort unten mit dem Sichtbarkeits-Widget.
Russell Zornes
Wie in den Kommentaren nach oben angegeben, wird das Widget bei Verwendung von Deckkraft im renderTree gerendert. In einigen Fällen ist dies nicht das, was Sie möchten. Die Verwendung des Sichtbarkeits-Widgets wird am meisten empfohlen.
Isac Moura
Ein Widget unsichtbar zu machen und die Deckkraft as0 zu haben, sind zwei verschiedene Dinge. Mit einem unsichtbaren Widget können Sie immer noch damit interagieren, es ist einfach unsichtbar. Mit dem Sichtbarkeits-Widget können Sie das Widget entfernen, bis es benötigt wird.
UndercoverCoder
171

Unsichtbar : Das Widget nimmt physischen Platz auf dem Bildschirm ein, ist jedoch für den Benutzer nicht sichtbar.

Vorbei : Das Widget benötigt keinen physischen Speicherplatz und ist vollständig verschwunden.


Unsichtbares Beispiel

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

Beispiel gegangen

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

Alternativ können Sie die ifBedingung sowohl für unsichtbar als auch für verschwunden verwenden.

Column(
  children: <Widget>[
    if (show) Text("This can be visible/not depending on condition"),
    Text("This is always visible"),
  ],
) 
CopsOnRoad
quelle
16
Dieser "Wenn" -Zustand ist perfekt!
Johnc
Ich liebe Flattern ❤️
Nipunasudha
61

Mit der Frage zusammenarbeiten und ein Beispiel für das Ersetzen durch eine leere Frage zeigen Container().

Hier ist das folgende Beispiel:

Geben Sie hier die Bildbeschreibung ein

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],
                          ),
                        ),
                      ),
                    ],
                  ),
                )
              ),
            ],
          )                    
        ],
      )
    );
  }
}
rafaelcb21
quelle
5
Dies sollte die akzeptierte Antwort sein. Dies ist die korrekte Implementierung von "Widgets programmgesteuert
ein-
Ja, dies sollte auf jeden Fall akzeptiert werden, da hierfür eine Grundsäule von Flutter verwendet wird, z. B. setState (). Wie können Sie sonst in Ihrem Stateful-Widget zwischen Visible / InVisible hin und her wechseln?
Yo Apps
27

Flutter enthält jetzt ein Sichtbarkeits-Widget , mit dem Sie Widgets ein- / ausblenden sollten. Das Widget kann auch zum Wechseln zwischen zwei Widgets verwendet werden, indem der Ersatz geändert wird.

Dieses Widget kann alle sichtbaren, unsichtbaren, verschwundenen und vieles mehr Zustände erreichen.

    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
    ),
Edmore M Gonese Digolodollarz
quelle
19

Probieren Sie das OffstageWidget aus

Wenn Attribut offstage:truedas den physischen Raum nicht einnimmt und unsichtbar ist,

Wenn Attribut offstage:false, wird es den physischen Raum einnehmen und sichtbar sein

Offstage(
   offstage: true,
   child: Text("Visible"),
),
Android-Team
quelle
Hinweis dazu: In den Flutter-Dokumenten heißt es: "Offstage kann verwendet werden, um die Abmessungen eines Widgets zu messen, ohne es (noch) auf dem Bildschirm anzuzeigen. Um ein Widget aus der Ansicht auszublenden, während es nicht benötigt wird, entfernen Sie das Widget lieber vollständig aus dem Baum anstatt es in einem Offstage-Teilbaum am Leben zu erhalten. "
lukeic vor
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('');
                  },),
                ),
              ),
            ),
          ),
          ),
Alan John
quelle
9

In Flutter 1.5 und Dart 2.3 können Sie die Sichtbarkeit mithilfe einer if-Anweisung in der Sammlung festlegen, ohne Container verwenden zu müssen.

z.B

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

          ],
        )
nonybrighto
quelle
Das ist so viel besser als die Optionen, die in der vorherigen Flatter- / Dart-Version verfügbar waren. Danke!
Hammer
8

Sie können jedes Widget in Ihrem Code mit einem neuen Widget namens (Sichtbarkeit) kapseln. Dies erfolgt über die gelbe Lampe ganz links im Widget, damit es nicht sichtbar ist

Beispiel: Angenommen, Sie möchten eine Zeile unsichtbar machen:

  1. Klicken Sie in die Lampe und wählen Sie (Mit Widget umschließen)
  2. Benennen Sie das Widget in Sichtbarkeit um
  3. Fügen Sie die sichtbare Eigenschaft hinzu und setzen Sie sie auf false
  4. Das untergeordnete Element des neu erstellten Widgets (Sichtbarkeits-Widget) ist das Widget, das unsichtbar sein soll

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

Ich hoffe, es wird in Zukunft jemandem helfen

Mohammed H. Hannoush
quelle
5

Versuchen Sie dies auch für Anfänger.

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";
      }
    });
  }
}
Hitesh Danidhariya
quelle
3

Aktualisieren

Flutter hat jetzt ein Sichtbarkeits- Widget. Um Ihre eigene Lösung zu implementieren, beginnen Sie mit dem folgenden Code.


Erstellen Sie selbst ein Widget.

Anzeigen Ausblenden

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

anzeigen / entfernen

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

Hat übrigens jemand einen besseren Namen für die oben genannten Widgets?


Mehr liest

  1. Artikel zum Erstellen eines Sichtbarkeits-Widgets.
Amsakanna
quelle
3

Wie bereits von @CopsOnRoad hervorgehoben, können Sie das Sichtbarkeits-Widget verwenden. Wenn Sie jedoch den Status beibehalten möchten, z. B. wenn Sie einen Viewpager erstellen und eine bestimmte Schaltfläche basierend auf der Seite ein- und ausblenden möchten, können Sie dies auf diese Weise tun

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

Vielleicht können Sie die Navigator-Funktion so verwenden Navigator.of(context).pop();

Onkar Nirhali
quelle
-7

Eine Lösung besteht darin, diese Widget-Farbeigenschaft auf Colors.transparent zu setzen. Zum Beispiel:

IconButton(
    icon: Image.asset("myImage.png",
        color: Colors.transparent,
    ),
    onPressed: () {},
),
edmond
quelle
1
Keine gute Lösung, da das Transparente IconButtonimmer noch Klicks erhält und Platz einnimmt. Bitte bearbeiten oder löschen Sie diese Antwort, bevor die Leute sie ablehnen.
CopsOnRoad