Flutter隐藏控件方法介绍

一、说明

在 Android 开发中,我们如果想隐藏一个控件只需要设置 visibility 属性为 inVisible 和 gone 即可,因为这个是基类 View 自带的属性,所有子 View 都通用。而 Flutter 的开发却不能如此直接,由于 Flutter 本着“一切皆组件”的原则,这类型的设置基本上只能通过组件去设置,下面总结一下隐藏控件的几种方法。

二、具体方法

方法1:Visibility 组件
Widget getWidget() {
  return Visibility (
    visible: false, // 设置是否可见:true:可见 false:不可见
    child: Text('Hello World')
  );
}
方法2:OffStage 组件
Widget getWidget() {
  return Offstage (
    offstage: true, // 设置是否可见:true:不可见 false:可见
    child: Text('Hello World')
  );
}
方法3:Opacity 组件
Widget getWidget() {
  return Opacity (
    opacity: 0.0, // 设置是否可见:0:不可见 1:可见
    child: Text('Hello World')
  );
}
方法4:设置 size
Widget getWidget4() {
  return Container (
    height: 0.0, // 设置是否可见:0:不可见 指定尺寸:可见
    child: Text('Hello World')
  );
}
方法5:空组件占位
bool isHideWidget = true;
getWidget() {
  return isHideWidget ? Container() : Text('Hello World');
}

1.假如仅仅判断是否显示 且不保留位置 用 Offstage

 Offstage(
    offstage: 布尔值,    当为true时,将隐藏组件且不保留空间位置
    child: 组件,)

注意:如果Offstage 和  Positioned 一起使用,要把 Offstage  放Positioned里面,包裹 Positioned 会出现问题

2.假如仅仅判断是否显示  且保留位置 用组件Opacity

body: new Center(
        child: new Opacity(
            opacity: 0.1,
          child: new Container(
            height: 100.0,
            width: 250.0,
            color: Colors.red,
          ),
        ),
      )

3. 假如判断两个控件是否显示哪个控件  用  Visibility  replacement 属性就是要显示的另一个控件

Visibility(
  //vip过期 或者数据为空 展示的视图
  replacement: brandItemModel == null
      ? Container()
      : Container(
          child: Image.asset(
            ImgAssets.icon_icon_com,
            scale: 2.1,
          ),
        ),
//vip下要展示的视图
  visible: !DateUtils.timeVipDiss(brandItemModel?.vipEndtime),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [
      Container(
        child: Image.asset(
          ImgAssets.icon_tip_mxt,
          scale: 2.1,
        ),
      ),
      SizedBox(
        width: 5,
      ),
      Text("盟信通认证,真实品牌商家",
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
          style: pingFangM(10, color: Color(0xFF666666))),
      Container(
        child: Image.asset(
          ImgAssets.icon_toward_light,
          scale: 2.5,
        ),
      )
    ],
  ),
)

三、问题

问题1:Offstage 和 Visibility 有什么区别,分别的应用场景是什么?

其实大多时候感觉区别不是很大,Offstage 提供的属性比较少,感觉是专门用来做简单的显示和隐藏的, Visibility 会提供较多的一些特性:

看完属性介绍有所了解:我们一般的需求用哪个都可以,如果有一些类似“不可见时展示一个默认的组件”等这类型需求,可以用 Visibility 组件实现。

Visibility构造器

const Visibility({
    Key key,
    @required this.child,
    this.replacement = const SizedBox.shrink(), // 不可见时显示的组件,只有maintainState=false才会显示。
    this.visible = true, // 是否可见
    this.maintainState = false, // 隐藏后是否位置组件状态
    this.maintainAnimation = false, // 隐藏后是否维持子组件中的动画
    this.maintainSize = false, // 隐藏后所占空间是否释放
    this.maintainSemantics = false,
    this.maintainInteractivity = false, // 隐藏后是否能够照常响应事件
  }) : assert(child != null),
       assert(replacement != null),
       assert(visible != null),
       assert(maintainState != null),
       assert(maintainAnimation != null),
       assert(maintainSize != null),
       assert(maintainState == true || maintainAnimation == false, 'Cannot maintain animations if the state is not also maintained.'),
       assert(maintainAnimation == true || maintainSize == false, 'Cannot maintain size if animations are not maintained.'),
       assert(maintainSize == true || maintainSemantics == false, 'Cannot maintain semantics if size is not maintained.'),
       assert(maintainSize == true || maintainInteractivity == false, 'Cannot maintain interactivity if size is not maintained.'),
       super(key: key);

注意:注意Visibility构造其中的断言部分:当maintainState为false时,maintainAnimation必须为false;当maintainAnimation为false时,maintainSize必须为false;当maintainSize为false时,matianInteractivety必须为false。

demo:

import 'package:flutter/material.dart';

class OffstageDemo extends StatefulWidget{
  @override
  _OffstageDemoState createState() {
    // TODO: implement createState
    return _OffstageDemoState();
  }
}

class _OffstageDemoState extends State<OffstageDemo>{
  bool _isShow = false;
  bool _visible = true;
  bool _saveSpace = false;
  bool _isInteractive = false;
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          SwitchListTile(
            value: _isShow,
            title: Text('Offstage(是否隐藏)'),
            onChanged: (val) => setState(() => _isShow = !_isShow),
          ),
          Offstage(
            offstage: _isShow,
            child: Container(
              constraints: BoxConstraints.tight(Size(200.0, 100.0)),
              margin: EdgeInsets.symmetric(vertical: 40.0),
              color: Colors.blue,
            ),
          ),
          Container(
            constraints: BoxConstraints.tight(Size(200.0, 100.0)),
            color: Colors.yellow,
            margin: EdgeInsets.only(bottom: 40.0),
          ),
          Divider(),
          SwitchListTile(
            value: _visible,
            title: Text('Visibility(是否可见)'),
            onChanged: (val) => setState(() => _visible = val),
          ),
          SwitchListTile(
            title: Text('是否占用空间'),
            value: _saveSpace,
            onChanged: (val) => setState((){
              _saveSpace = val;
              // ignore: unnecessary_statements
              !_saveSpace && (_isInteractive = false);
            }),
          ),
          SwitchListTile(
            title: Text('隐藏后是否响应事件'),
            value: _isInteractive,
            onChanged: (val) => setState((){
              _isInteractive = val;
              // ignore: unnecessary_statements
              _isInteractive && (_saveSpace = true);
            }),
          ),
          Visibility(
            visible: _visible,
            maintainState: true,
            maintainAnimation: true,
            maintainSize: _saveSpace,
            maintainInteractivity: _isInteractive,
            child: GestureDetector(
              child: Container(
                constraints: BoxConstraints.tight(Size(200.0, 100.0)),
                margin: EdgeInsets.symmetric(vertical: 40.0),
                color: Colors.blue,
              ),
              onTap: () {
                print('tap');
              },
            ),
          ),
          Container(
            constraints: BoxConstraints.tight(Size(200.0, 100.0)),
            color: Colors.yellow,
            margin: EdgeInsets.only(bottom: 40.0),
          ),
        ],
      ),
    );
  }
}

运行结果:

在这里插入图片描述

在Visibility示例中,当蓝色部分隐藏后,将是否占用空间隐藏后是否响应事件开关激活,这时之前的蓝色Container所拥有的的空间被保留了下来,点击这块空白区域,控制台还可以打印tap。关闭隐藏后是否响应事件后,再点击空白区域,控制台将不再打印tap。 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值