You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何实现点击开关时动画隐藏密码输入框并同步移动其他组件

问题原因

你的动画不生效、切换生硬有两个核心问题:

  1. AnimatedSwitcher的两个子组件都是无唯一标识Key的Column,Flutter在Diff组件树时会判定为同一组件,不会触发过渡动画;
  2. 你用了两个布局结构差异很大的_on/_off方法返回不同的Column,用flex占比控制位置,本身就没有做过渡联动的基础,AnimatedSwitcher默认的淡入淡出效果也满足不了「密码框收起时下方组件同步上移」的需求。

解决方案

调整布局结构,不要拆分两个完全不同的Column,将可变的密码输入框区域用动画组件包裹,通过动画控制其高度、透明度,下方的开关组件自然会跟随布局变化平滑移动。修改后的代码如下:

import 'package:flutter/material.dart';

import 'forget_password_text.dart';
import 'password_text_field.dart';
import 'premium_mode_switch.dart';

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

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

class _FrontLayerLeftSidePasswordHidingState
    extends State<FrontLayerLeftSidePasswordHiding> with SingleTickerProviderStateMixin {
  bool _visible = true;
  late AnimationController _animationController;
  late Animation<double> _sizeAnimation;
  late Animation<double> _opacityAnimation;

  @override
  void initState() {
    super.initState();
    // 动画时长可自行调整
    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
    _sizeAnimation = Tween<double>(begin: 1, end: 0).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    ));
    _opacityAnimation = Tween<double>(begin: 1, end: 0).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    ));
    // 初始化状态匹配
    if (_visible) {
      _animationController.value = 0;
    } else {
      _animationController.value = 1;
    }
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 密码输入框动画区域
        SizeTransition(
          sizeFactor: _sizeAnimation,
          axisAlignment: -1,
          child: AnimatedOpacity(
            opacity: _opacityAnimation.value,
            duration: Duration.zero,
            child: const SizedBox(
              // 可根据实际布局调整高度,也可替换为Expanded适配
              height: 120,
              child: Column(
                children: [
                  Spacer(flex: 5),
                  Expanded(flex: 10, child: PasswordTextField()),
                ],
              ),
            ),
          ),
        ),
        // 开关区域占比固定,会跟随上方区域高度变化自动移动
        Expanded(
          flex: 10,
          child: Row(
            children: [
              const Spacer(flex: 13),
              const Expanded(flex: 10, child: ForgetPasswordText()),
              const Spacer(flex: 20),
              Expanded(
                flex: 10,
                child: PremiumModeSwitch(
                  onChanged: () {
                    setState(() {
                      _visible = !_visible;
                      _visible ? _animationController.reverse() : _animationController.forward();
                    });
                  },
                ),
              ),
              const Spacer(flex: 10),
            ],
          ),
        ),
        const Spacer(flex: 14),
      ],
    );
  }
}

效果说明

修改后开关切换时,密码输入框会逐渐变透明同时高度收缩为0,下方的忘记密码文本、开关组件会同步平滑上移,完全符合需求的过渡效果。


内容的提问来源于stack exchange,提问作者portlek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 13:42:01