在Android中,每个单独的View子类都有一个setVisibility()方法,允许你修改View对象的可见性

有3个设置可见性的选项:

可见:在布局中显示视图 不可见:隐藏视图,但留下一个空白,相当于视图在可见时所占据的空白 消失:隐藏视图,并将其完全从布局中移除。就好像它的高和宽都是0dp

对于Flutter中的小部件,是否有与上述相同的东西?

快速参考: https://developer.android.com/reference/android/view/View.html#attr_android:visibility


更新:因为这个答案是写的,可见性被引入,并提供了这个问题的最佳解决方案。


你可以在不透明度:为0.0的情况下使用不透明度来绘制隐藏的元素,但仍然占用空间。

为了使它不占用空间,将其替换为空Container()。

编辑: 要将它包装在不透明对象中,请执行以下操作:

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

谷歌开发者不透明度快速教程:https://youtu.be/9hltevOHQBw


与问题协作,并展示一个用空Container()替换它的示例。

下面是一个例子:

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

初学者也可以试试。

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

定义:

不可见:小部件占用屏幕上的物理空间,但对用户不可见。这可以使用可见度小部件来实现。

消失:小部件不占用任何物理空间,完全消失。这可以使用Visibility, if或if-else条件来实现。

无形的例子:

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

例子:

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

使用如果:

对于一个孩子: 列( 孩子们:<部件> ( Text('Good Morning'), //始终可见 if (wishOnePerson) Text(' Mr ABC'), //只有条件为真时才可见 ), ) 对于多个孩子: 列( 孩子:( Text('Good Morning'), //始终可见 如果(但愿)……[//只有当condition为true时,这些子元素才可见 文本(“ABC先生”), 文本(“DEF先生”), 文本(“某某先生”), ), ), )

使用if - else:

对于一个孩子: 列( 孩子们:<部件> ( //基于'isMorning'条件,只有一个是可见的 if (isMorning) Text('Good Morning') Text ('Good Evening'), ), ) 对于多个孩子: 列( 孩子:( //在' beforeSunset '条件下,只会显示一个子元素 if (beforeSunset)…[ 文本(“早上好”), 文本('下午好'), 其他的…[ 文本(“晚上好”), 文本('晚安'), ), ), )


更新

Flutter现在有一个可见性小部件。要实现您自己的解决方案,请从下面的代码开始。


自己做一个小部件。

显示/隐藏

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

显示/删除

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

顺便问一下,有没有人对上面的小部件有更好的名字?

更多的阅读

关于如何制作可见性小部件的文章。


Flutter现在包含一个可见性小部件,您可以使用它来显示/隐藏小部件。小部件还可以通过更改替换来在两个小部件之间切换。

这个小部件可以实现任何可见、不可见、消失等状态。

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

尝试Offstage小部件

如果属性off - stage:true则不占用物理空间且不可见,

如果属性offstage:false它将占用物理空间而可见

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

在flutter 1.5和Dart 2.3中,对于可视性消失,您可以在集合中使用if语句设置可见性,而不必使用容器。

e.g

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

          ],
        )

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

正如@CopsOnRoad已经强调的那样, 您可以使用Visibility小部件。但是,如果你想保持它的状态,例如,如果你想建立一个viewpager,让一个按钮根据页面出现和消失,你可以这样做

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,
              child: "your widget"
            )
          ],
        ),
      )
    ]))

你可以在你的代码中用一个叫做(Visibility)的新小部件封装任何小部件,这是你想让它不可见的小部件最左边的黄色灯

例如:假设你想让一行不可见:

Click in the lamp and choose (Wrap with widget) Rename the widget to Visibility Add the visible property and set it to false The Child of the newly created widget (Visibility Widget) is the Widget that you want it to be invisible Visibility( visible: false, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ SizedBox( width: 10, ), Text("Search", style: TextStyle(fontSize: 20 ),), ], ), ),

我希望它能在将来帮助到别人


也许你可以像这样使用Navigator函数Navigator.of(context).pop();


恕我直言,在Flutter中不需要可见性属性或特殊的小部件,因为如果你不需要显示小部件,就不要将其添加到小部件树中或将其替换为空小部件:

  @override
  Widget build(BuildContext context) {
    return someFlag ? Text('Here I am') : SizedBox();
  }

我认为能见度小部件存在的原因是因为很多人问:)人们习惯了由某些属性控制的元素的可见性


在Flutter中有很多不同的方法来实现这一点。在我解释它们之前,我将首先提供与android原生“隐形”和“消失”等价的快速解决方案:

视图。看不见的:

Opacity(
  opacity: 0.0,
  child: ...
)

视图。了:

Offstage(
  child: ...
)

现在让我们比较一下这些方法和其他方法:

不透明度

这个小部件将不透明度(alpha)设置为您想要的任何值。将其设置为0.0比设置为0.1略显不明显,所以希望这很容易理解。小部件仍将保持其大小和占用相同的空间,并保持每个状态,包括动画。由于它留下了一个间隙,用户仍然可以触摸或点击它。(顺便说一下,如果你不想让人们触摸一个看不见的按钮,你可以用一个IgnorePointer小部件来包装它。)

后台

这个小部件隐藏了子小部件。你可以把它想象成把小部件放在“屏幕外面”,这样用户就看不到它了。小部件仍然要完成颤振管道中的所有内容,直到它到达最后的“绘制”阶段,在这个阶段它根本不绘制任何东西。这意味着它将维护所有的状态和动画,但不会在屏幕上呈现任何东西。此外,它在布局时也不会占用任何空间,不会留下任何空隙,用户自然无法点击。

可见性

这个小部件结合了上述(以及更多)功能,方便您使用。它有参数,如maintainState, maintainAnimation, maintainSize, maintainInteractivity等。根据你设置这些属性的方式,它由以下决定:

if you want to maintain state, it will either wrap the child with an Opacity or with an Offstage, depends on whether you also want to maintain size. Further, unless you want to maintainInteractivity, it will also wrap an IgnorePointer for you, because clicking on a transparent button is kinda weird. if you don't want to maintainState at all, it directly replaces the child with a SizedBox so it's completely gone. You can change the blank SizedBox to anything you want, with the replacement property.

删除小部件

如果您不需要维护状态等,通常建议完全从树中删除小部件。例如,您可以使用if (condition)来决定是否将小部件包含在列表中,或者使用condition ?child: sizebox()直接用sizebox替换它。这样可以避免不必要的计算,并且对于性能来说是最好的。


class VisibilityExample extends StatefulWidget {
  const VisibilityExample({Key? key}) : super(key: key);

  @override
  _VisibilityExampleState createState() => _VisibilityExampleState();
}

class _VisibilityExampleState extends State<VisibilityExample> {
  bool visible = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Lines'),
      ),
      body: Container(
        color: Colors.black87,
        child: Stack(alignment: Alignment.bottomCenter, children: [
          ListView(
            shrinkWrap: true,
            children: [
              Container(
                height: 200,
              ),
              InkWell(
                onTap: () {},
                onHover: (value) {
                  print(value);
                  setState(() {
                    visible = !visible;
                  });
                },
                child: Visibility(
                  maintainSize: true,
                  maintainAnimation: true,
                  maintainState: true,
                  visible: visible,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      IconButton(
                        color: Colors.white54,
                        icon: const Icon(
                          Icons.arrow_left_outlined,
                        ),
                        onPressed: () {},
                      ),
                      const SizedBox(
                        width: 5,
                      ),
                      IconButton(
                        color: Colors.white54,
                        icon: const Icon(
                          Icons.add_circle_outlined,
                        ),
                        onPressed: () {},
                      ),
                      const SizedBox(
                        width: 5,
                      ),
                      IconButton(
                        color: Colors.white54,
                        icon: const Icon(
                          Icons.remove_circle,
                        ),
                        onPressed: () {},
                      ),
                      const SizedBox(
                        width: 5,
                      ),
                      IconButton(
                        color: Colors.white54,
                        icon: const Icon(
                          Icons.arrow_right_outlined,
                        ),
                        onPressed: () {},
                      ),
                      const SizedBox(
                        width: 5,
                      ),
                      IconButton(
                        color: Colors.white54,
                        icon: const Icon(Icons.replay_circle_filled_outlined),
                        onPressed: () {},
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ]),
      ),
    );
  }
}