以编程方式在Flutter上显示/隐藏小部件

时间:2017-06-11 23:59:41

标签: android widget dart visibility flutter

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

设置可见性有3个选项:

  • 可见:呈现布局中可见的View
  • 隐形:隐藏View,但留下的差距相当于View如果可见则会占用的差距
  • 消失:隐藏View,并将其从布局中完全删除。就像它的heightwidth0dp
  • 一样

Flutter中的Widgets是否有与上述相同的内容?

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

15 个答案:

答案 0 :(得分:35)

要与问题协作并显示使用空Container()替换它的示例。

以下是以下示例:

enter image description here

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

答案 1 :(得分:34)

不可见:该小部件占据了屏幕上的物理空间,但对用户不可见。

已消失:该小部件不占用任何物理空间,并且完全消失了。


不可见的示例

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

示例

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

答案 2 :(得分:20)

您可以array.joinTo(System.out, separator = " ") { n -> "${n * n}" } 使用Opacity opacity:来绘制隐藏元素,但仍会占用空间。

要使其不占用空间,请将其替换为空0.0

编辑: 要将其包装在Opacity对象中,请执行以下操作:

Container()

Google Developers关于不透明度的快速教程:https://youtu.be/9hltevOHQBw

答案 3 :(得分:13)

您可以使用名为(Visibility)的新小部件将代码中的任何小部件封装起来,这是从您希望其不可见的小部件最左侧的黄灯亮起的

示例:说您要使行不可见:

  1. 单击灯并选择(包装小部件)
  2. 将小部件重命名为“可见性”
  3. 添加visible属性并将其设置为false
  4. 新创建的小部件(可见性小部件)的子级是 您希望它不可见

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

我希望它将对以后的人有所帮助

答案 4 :(得分:8)

Flutter现在包含一个Visibility Widget,您应该使用它来显示/隐藏小部件。通过更改替换,该小部件还可用于在2个小部件之间切换。

此小部件可以实现任何可见,不可见,消失等状态。

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

答案 5 :(得分:5)

恕我直言,如果您不需要显示小部件,则 Flutter 中不需要可见性属性或特殊小部件,只是不要将其添加到小部件树或将其替换为空小部件:

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

我认为 Visibility 小部件存在的原因是因为很多人问:) 人们习惯于通过某些属性控制元素的可见性

答案 6 :(得分:2)

对于初学者也可以尝试此操作。

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

答案 7 :(得分:2)

flutter 1.5 Dart 2.3 中,可见性消失了,您可以通过使用集合中的if语句来设置可见性,而不必使用容器。

例如

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

          ],
        )

答案 8 :(得分:1)

更新

Flutter现在具有一个Visibility小部件。要实施自己的解决方案,请从以下代码开始。


自己制作一个小部件。

显示/隐藏

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

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


更多阅读内容

  1. Article关于如何制作可见性小部件。

答案 9 :(得分:1)

尝试“后台”窗口小部件 如果属性offstage:true,则不占用物理空间且不可见, 如果属性offstage:false,它将占用物理空间并且可见

后台(    台下:是的,    子级:Text(“ Visible”), ),

答案 10 :(得分:1)

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

答案 11 :(得分:1)

有条件地添加/删除小部件

要包括/排除小部件:

if (this.isLuckyTime) TextButton(
 child: Text('I am feeling lucky')
)

如果您想让小部件不可见但仍保持其大小,请将其包裹在 <Visibility> 中并设置 maintainSize: true。如果它是有状态的并且您需要保持它的状态,那么还要添加 maintainState: true

动画小部件淡入淡出

要使小部件平滑地淡入淡出,您可以使用 AnimatedOpacity

AnimatedOpacity(
   opacity: this.isLuckyTime ? 1.0 : 0.0,
   duration: Duration(milliseconds: 500),
   child: Text('I am feeling lucky')
)

特别是对于来自原生 android 的开发人员:值得一提的是,您从不显示/隐藏小部件,无论是否使用您需要的小部件,都可以重新绘制 UI:

? Introduction to declarative UI
?State Management
? Simple app state management

答案 12 :(得分:0)

正如@CopsOnRoad突出显示的那样, 您可以使用“可见性”小部件。但是,例如,如果您想保持其状态,则要构建一个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 == true ? true : false,
              child: "your widget"
            )
          ],
        ),
      )
    ]))

答案 13 :(得分:0)

也许您可以使用Navigator.of(context).pop();这样的导航器功能

答案 14 :(得分:-3)

一种解决方案是将tis小部件的color属性设置为Colors.transparent。例如:

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