点击Stack中小部件时如何平滑切换堆叠组件并实现缩放动画
Flutter Stack堆叠组件平滑切换效果实现
以下是完整可运行的实现代码,核心通过Flutter隐式动画实现平滑过渡,同时动态调整子组件顺序控制堆叠层级:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Stack堆叠切换效果')), body: const StackSwitchDemo(), ), ); } } class StackSwitchDemo extends StatefulWidget { const StackSwitchDemo({super.key}); @override State<StackSwitchDemo> createState() => _StackSwitchDemoState(); } class _StackSwitchDemoState extends State<StackSwitchDemo> { // 记录第一个组件是否为放大状态 bool _isFirstLarge = true; // 统一动画时长 final Duration _animDuration = const Duration(milliseconds: 300); // 放大/缩小状态的尺寸 final double _largeSize = 300; final double _smallSize = 150; @override Widget build(BuildContext context) { return Stack(children: _buildStackChildren()); } List<Widget> _buildStackChildren() { final Widget widgetA = _buildStackItem( title: "Widget A", color: Colors.blueAccent, isLarge: _isFirstLarge, onTap: () { // 仅当前组件为缩小状态时点击才触发切换 if (!_isFirstLarge) setState(() => _isFirstLarge = true); }, ); final Widget widgetB = _buildStackItem( title: "Widget B", color: Colors.orangeAccent, isLarge: !_isFirstLarge, onTap: () { if (_isFirstLarge) setState(() => _isFirstLarge = false); }, ); // 放大状态的组件放在列表末尾,保证堆叠层级更高不被遮挡 return _isFirstLarge ? [widgetB, widgetA] : [widgetA, widgetB]; } Widget _buildStackItem({ required String title, required Color color, required bool isLarge, required VoidCallback onTap, }) { return AnimatedPositioned( duration: _animDuration, curve: Curves.easeInOut, // 放大组件固定在左上,缩小组件放在右下 left: isLarge ? 20 : MediaQuery.of(context).size.width - _smallSize - 20, top: isLarge ? 20 : MediaQuery.of(context).size.height - _smallSize - 100, child: GestureDetector( onTap: onTap, child: AnimatedContainer( duration: _animDuration, curve: Curves.easeInOut, width: isLarge ? _largeSize : _smallSize, height: isLarge ? _largeSize : _smallSize, color: color, child: Center( child: Text(title, style: const TextStyle(color: Colors.white, fontSize: 24)), ), ), ), ); } }
实现关键点
- 用
AnimatedPositioned和AnimatedContainer组合实现位置、尺寸的同步平滑过渡,无需手动管理动画控制器 - 仅缩小状态的组件可触发点击切换,避免无效状态更新
- 动态调整Stack子组件列表顺序,无需额外设置层级属性即可同步变更堆叠顺序
内容的提问来源于stack exchange,提问作者loalexzzzz
相关产品推荐
相关产品推荐

