Flutter实现京东搜索结果的下拉选项和遮罩效果

通过Stack + 动画
1.Stack组件可以让后面的组件覆盖在前一个上面,我们可以使用Stack来进行嵌套
2.动画部分

late Animation<double> animation;
late AnimationController controller;
AnimationStatus? animationState;


  void initState() {
    super.initState();
    itemList = copyWithList(widget.data.map((e) => e).toList());
    // 动画控制器
    controller = AnimationController(
        duration: const Duration(milliseconds: 100), vsync: this);
    // 动画方式
    animation = Tween<double>(begin: 0, end: 100).animate(controller)
      ..addListener(() {
        setState(() {
       		animationValue = animation.value
        });
      })
      ..addStatusListener((AnimationStatus state) {
        setState(() {
         	animationState = state;
        });
      });
  }

3.stack部分

Stack(
        children: [
          // 撑满
          Container(
            height: double.infinity,
          ),
          // 底层滚动的列表
          Positioned(
            top: 50,
            bottom: 12,
            left: 0,
            right: 0,
            child: SingleChildScrollView(
            	child:Column(
					children:[
						Container(
							color: Colors.red,
							height: 300,
							width: double.infinity,
							child: const Text("1111111"),
						),
						Container(
							color: Colors.blue,
							height: 300,
							width: double.infinity,
							child: const Text("1111111"),
						),
						Container(
							color: Colors.green,
							height: 300,
							width: double.infinity,
							child: const Text("1111111"),
						),
					]
				)
            )
          ),
          // 选项栏
          Container(
            color: Colors.white,
            child: Padding(
              padding: const EdgeInsets.symmetric(
                horizontal: 16,
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Expanded(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: selects.asMap().keys.map(
                        (e) {
                          return InkWell(
                            onTap: () {
                              if (selects[e]['text'] == '排序') {
                                itemList = itemList.reversed.toList();
                              }
                              setState(() {
                                index = e;
                                for (int i = 0; i < selects.length; 
                                  if (e == i) {
                                    setState(() {
                                      selects[e]['isSelect'] =
                                          !selects[e]['isSelect'];
                                    });
                                    if (e == 2) {
                                      selects[e]['isSelect']
                                          ? controller.reverse()
                                          : controller.forward();
                                    } else {
                                      controller.reset();
                                    }
                                  } else {
                                    setState(() {
                                      selects[i]['isSelect'] = true;
                                    });
                                  }
                                }
                              });
                            },
                            child: Row(
                              children: [
                                Text(
                                  selects[e]['text'],
                                  style: TextStyle(
                                      fontSize: 16,
                                      color: index == e
                                          ? Colors.green
                                          : Colors.black),
                                ),
                                Icon(selects[e]['isSelect']
                                    ? Icons.arrow_drop_down
                                    : Icons.arrow_drop_up),
                              ],
                            ),
                          );
                        },
                      ).toList(),
                    ),
                  ),
                  Row(
                    children: [
                      TextButton(
                        onPressed: () {},
                        child: const Text(
                          "通知",
                          style: TextStyle(
                            color: Color(0xff0FAB6B),
                            fontSize: 16,
                          ),
                        ),
                      ),
                      CupertinoSwitch(
                        value: isChange,
                        onChanged: (bool val) {
                          setState(() {
                            isChange = val;
                          });
                        },
                        activeColor: const Color(0xff0FAB6B),
                      )
                    ],
                  )
                ],
              ),
            ),
          ),
          // 阴影,遮罩部分
          Positioned(
            top: 40,
            left: 0,
            right: 0,
            bottom: 0,
            child: !selects[2]['isSelect']
                ? SizedBox(
                    child: InkWell(
                      child: AnimatedBuilder(
                        animation: animation,
                        builder: (context, child) {
                          // 这里是下拉框下方阴影 点击阴影隐藏下拉框
                          return Container(
                            width: double.infinity,
                            height:MediaQuery.of(context).size.height,
                            color: Colors.black.withOpacity(0.5),
                          );
                        },
                      ),
                      onTap: () {
                        cancal();
                      },
                    ),
                  )
                : const SizedBox(),
          ),
          // 弹出框
          Positioned(
            top: 40,
            left: 0,
            right: 0,
            child: AnimatedBuilder(
              animation: animation,
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    InkWell(
                      onTap: () {
                        statusCount = 2;
                        selects[2]['text'] = '状态';
                        itemList = widget.data;
                        cancal(); // 因为这个函数中有setState,所以上面不用写
                      },
                      child: Container(
                        height: 30,
                        padding: const EdgeInsets.only(left: 30),
                        child: Row(
                          children: [
                            Icon(
                              Icons.check,
                              color: statusCount == 2
                                  ? Colors.red
                                  : Colors.transparent,
                            ),
                            const Text(
                              "全部",
                              style: TextStyle(
                                fontSize: 16,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                    InkWell(
                      onTap: () {
                        statusCount = 0;
                        selects[2]['text'] = '已停售';
                        itemList = widget.data
                            .where((element) => element['status'] == "已停售")
                            .toList();
                        cancal(); // 因为这个函数中有setState,所以上面不用写
                      },
                      child: Container(
                        height: 30,
                        padding: const EdgeInsets.only(left: 30),
                        child: Row(
                          children: [
                            Icon(
                              Icons.check,
                              color: statusCount == 0
                                  ? Colors.red
                                  : Colors.transparent,
                            ),
                            const Text(
                              "已停售",
                              style: TextStyle(
                                fontSize: 16,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                    InkWell(
                      onTap: () {
                        statusCount = 1;
                        selects[2]['text'] = '已成交';
                        itemList = widget.data
                            .where((element) => element['status'] == "已成交")
                            .toList();
                        cancal();
                      },
                      child: Container(
                        height: 30,
                        padding: const EdgeInsets.only(left: 30),
                        child: Row(
                          children: [
                            Icon(
                              Icons.check,
                              color: statusCount == 1
                                  ? Colors.red
                                  : Colors.transparent,
                            ),
                            const Text(
                              "已成交",
                              style: TextStyle(
                                fontSize: 16,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              builder: (context, child) {
                return Container(
                  height: animation.value,
                  decoration: const BoxDecoration(
                    borderRadius: BorderRadius.only(
                      bottomLeft: Radius.circular(16),
                      bottomRight: Radius.circular(16),
                    ),
                    color: Colors.white,
                  ),
                  child: child,
                );
              },
            ),
          ),
        ],
      )

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值