Flutter如何实现点击开关时动画隐藏密码输入框并同步移动其他组件
问题原因
你的动画不生效、切换生硬有两个核心问题:
AnimatedSwitcher的两个子组件都是无唯一标识Key的Column,Flutter在Diff组件树时会判定为同一组件,不会触发过渡动画;- 你用了两个布局结构差异很大的
_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
相关产品推荐
相关产品推荐

