Flutter中用AnimatedContainer实现类Hero动画的全屏适配问题
问题解决:AnimatedContainer点击后占满全屏并挤开其他容器
问题根源
你当前使用的水平ListView会允许子组件横向超出屏幕范围并支持滚动,因此蓝色容器宽度设置为屏幕宽度后,只会占据ListView的右侧区域,红色容器仍停留在左侧,无法实现"挤开"的效果。
解决方案
将父容器从ListView替换为Row,同时通过状态变量动态控制红色容器的宽度(蓝色放大时收缩至0),结合AnimatedContainer实现平滑的动画过渡:
import 'package:flutter/material.dart'; class AnimationTestView extends StatefulWidget { const AnimationTestView({Key? key}) : super(key: key); @override State<AnimationTestView> createState() => _AnimationTestViewState(); } class _AnimationTestViewState extends State<AnimationTestView> { bool isBig = false; @override Widget build(BuildContext context) { var padding = MediaQuery.of(context).padding; double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; double newHeight = height - padding.top - padding.bottom; return Scaffold( body: Row( children: [ // 红色容器:蓝色放大时收缩至0 AnimatedContainer( duration: const Duration(seconds: 1), height: newHeight / 2, width: isBig ? 0 : width / 2, color: Colors.red, ), GestureDetector( onTap: () { setState(() { isBig = !isBig; }); }, child: AnimatedContainer( duration: const Duration(seconds: 1), height: isBig ? newHeight : newHeight / 2, width: isBig ? width : width / 2, color: Colors.blue, ), ) ], ), ); } }
关键改动说明
- 替换父组件:用
Row替代ListView(scrollDirection: Axis.horizontal),让两个容器在同一行内布局,而非可滚动的列表。 - 红色容器动画:给红色容器也添加
AnimatedContainer,当isBig为true时将宽度设为0,实现平滑收缩的效果。 - 蓝色容器全屏逻辑:保持原有宽度和高度的动画逻辑,现在在
Row布局下,蓝色容器宽度设为屏幕宽度时会直接占满整个横向空间,同时高度扩展至全屏。
如果需要更贴近Hero动画的"覆盖式"效果(而非挤开),也可以用Stack作为父容器,让蓝色容器在动画时从原来的位置扩展至全屏,红色容器被覆盖。但根据你的需求,上述Row+双AnimatedContainer的方案更贴合"挤开"的交互。
内容的提问来源于stack exchange,提问作者Henri Schröder
相关产品推荐
相关产品推荐

