如何在Flutter中以编程方式显示/隐藏小部件

322

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

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

  • Visible:在布局中呈现可见的View
  • Invisible:隐藏View,但保留与View等效的间隙,就像View是可见的一样
  • Gone:隐藏View并完全从布局中移除。就好像它的heightwidth0dp 一样。

在Flutter中是否有类似上述方式可以设置小部件的可见性?

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

16个回答

7

正如@CopsOnRoad所强调的那样,您可以使用可见性小部件。但是,如果您想保留其状态,例如,如果您想构建一个视图页面并根据页面使某个按钮出现和消失,可以按照以下方式操作

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

2
visible: isVisibileNextBtn == true ? true : false could by simplified as visible: isVisibileNextBtn - ndelanou

6

在我的看法中,Flutter 中不需要使用可见性属性或特殊的小部件来实现这个功能。如果您不需要显示一个小部件,则只需不将其添加到小部件树中,或使用一个空小部件替换它:

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

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


4

在Flutter中有很多种实现方式。 在我解释每一种方法之前,我先提供与Android本地“invisible”和“gone”等价的快速解决方案:

View.INVISIBLE:

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

View.GONE:

Offstage(
  child: ...
)

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

不透明度

这个小部件可以将不透明度(alpha)设置为任何值。将其设置为0.0与将其设置为0.1相比只是稍微不那么可见,希望这很容易理解。该小部件仍然保持其大小并占据相同的空间,并保持每个状态,包括动画。由于它会留下间隙,因此用户仍然可以触摸它或单击它。(顺便说一句,如果您不想让人们触摸看不见的按钮,则可以使用IgnorePointer小部件将其包装起来。)

离场

这个小部件隐藏了子小部件。您可以将其想象为将小部件“放在屏幕外”,以便用户看不见它。小部件仍然通过Flutter Pipeline中的所有内容,直到到达最终的“绘画”阶段,在那里它根本不会绘制任何内容。这意味着它将保留所有状态和动画,但只是不在屏幕上呈现任何内容。此外,在布局期间它也不会占据任何空间,不会留下空隙,自然用户也无法单击它。

可见性

这个小部件为您的方便结合了上述内容(以及更多内容)。它有诸如maintainStatemaintainAnimationmaintainSizemaintainInteractivity等参数。根据您设置这些属性的方式,它决定从以下内容中选择:

  1. 如果您想维护状态,则它将使用OpacityOffstage之一包装子项,具体取决于是否还要维护大小。此外,除非您想要maintainInteractivity,否则它还将为您包装一个IgnorePointer,因为单击透明按钮有点奇怪。

  2. 如果您根本不想maintainState,则直接用SizedBox替换child,以便它完全消失。您可以使用replacement属性将空白的SizedBox更改为任何您想要的内容。

删除小部件

如果您不需要维护状态等内容,则通常建议从树中彻底删除小部件。例如,您可以使用if(condition)来决定是否在列表中包含小部件,或者使用condition?child:SizedBox()将其直接替换为SizedBox。这样可以避免不必要的计算并获得最佳性能。


2
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: () {},
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ]),
      ),
    );
  }
}
 

enter image description here


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: 声明式UI介绍 状态管理 简单应用程序状态管理

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接