show/hide widgets on Flutter programmatically

2019-01-23 04:10发布

问题:

On Android, every single View subclass has a "setVisibility" method that allows you modify the visibility of a View object

There are 3 options of setting the visibility:

  • visibile: Renders the View visible inside the layout
  • invisible: Hides the View, but leaves a gap that is equivalent to what the View would occupy if it were visible
  • gone: Hides the View, and removes it entirely from the layout. It's as if its height and width were 0dp

Is there something equivalent to the above for Widgets in Flutter?

For a quick reference: https://developer.android.com/reference/android/view/View.html#attr_android:visibility

回答1:

You can use Opacity with an opacity of 0.0 to draw make an element hidden but still occupy space.

To make it not occupy space, replace it with an empty Container().

EDIT: To wrap it in an Opacity object, do the following:

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

Google Developers quick tutorial on Opacity: https://youtu.be/9hltevOHQBw



回答2:

To collaborate with the question and show an example of replacing it with an empty Container().

Here's the example below:

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


回答3:

Invisible: The widget takes physical space on the screen but not visible to user.

Gone: The widget doesn't take any physical space and is completely gone.


Update

Flutter added a new Widget called Visibility

Invisible example

Visibility(
  child: Container(color: Colors.blue, width: 100, height: 100),
  maintainSize: true, 
  maintainAnimation: true,
  maintainState: true,
  visible: false, 
),

Gone example

Visibility(
  child: Container(color: Colors.blue, width: 100, height: 100),
  visible: false,
),

Old Solution

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("My app"),),
        body: HomePage(),
      ),
    );
  }
}

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

class _HomePageState extends State<HomePage> {
  double opacity = 1.0;
  bool visible = true;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            Expanded(child: Opacity(opacity: opacity, child: Container(color: Colors.orange, height: 40.0,),),),
            visible ? Expanded(child: Container(color: Colors.green, height: 40.0,),) : Container(),
          ],
        ),
        Row(
          children: <Widget>[
            Expanded(child: RaisedButton(child: Text("Invisible"), onPressed: _hide,),),
            Expanded(child: RaisedButton(child: Text("Gone"), onPressed: _gone,),)
          ],
        ),
      ],
    );
  }

  void _hide() {
    setState(() => opacity = opacity == 0.0 ? 1.0 : 0.0);
  }

  void _gone() {
   setState(() => visible = !visible);
  }
}


回答4:

For beginner try this too.

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


回答5:

Flutter now contains a Visibility Widget that you should use to show/hide widgets. The widget can also be used to switch between 2 widgets by changing the replacement.

This widget can achieve any of the states visible, invisible, gone and a lot more.

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


回答6:

One solution is to set tis widget color property to Colors.transparent. For instance:

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


回答7:

Make a widget yourself.

show/hide

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

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

show/remove

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

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

By the way, does any have a better name for the widgets above?