Flutter:如何在Row组件中使用AnimatedPositioned并解决动画报错
问题解决:Row中使用AnimatedPositioned导致的错误与动画适配方案
错误原因
AnimatedPositioned是仅能作为Stack直接子组件的特殊组件,你把它嵌套在Row里,不仅它的定位属性(right)无法生效,还会触发"Incorrect use of ParentDataWidget"错误,这就是组件尺寸无法正确调整的核心原因。
无需改用AnimatedSize的简单方案
把Row里的隐形占位盒子换成AnimatedContainer,利用它的宽度动画来实现和侧边栏同步的过渡效果,完全适配Row的布局逻辑:
修改后的完整代码
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return const MaterialApp( home: Scaffold( body: SafeArea( child: Center( child: MyWidget(), ), ), ), ); } } class MyWidget extends StatefulWidget { const MyWidget({Key? key}) : super(key: key); @override State<MyWidget> createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { bool showSidebar = true; @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; return SafeArea( child: Stack( children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Expanded( child: SingleChildScrollView( child: Column( children: [ Container( width: double.maxFinite, height: 700, color: Colors.red, ), Text( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', softWrap: true, ), Container( width: double.maxFinite, height: 700, color: Colors.yellow, ), ], ), ), ), // 替换成AnimatedContainer实现宽度动画 AnimatedContainer( width: showSidebar ? 43 : 0, height: height, curve: Curves.ease, duration: const Duration(milliseconds: 100), color: Colors.transparent, ), ], ), // Sidebar box AnimatedPositioned( right: showSidebar ? 0 : -43, curve: Curves.ease, duration: const Duration(milliseconds: 100), child: Container( width: 43.0, height: height, color: Colors.blue, child: Column( mainAxisAlignment: MainAxisAlignment.start, children: const [ SizedBox(height: 100.0), Expanded( child: Center( child: RotatedBox( quarterTurns: -1, child: Text( 'EXAMPLE MENU BAR - PAGE 1', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Colors.white), ), ), ), ), ], ), ), ), Padding( padding: const EdgeInsets.only(left: 5.0, top: 5.0, right: 4.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ fakeButton(), Column( children: [ fakeButton(), fakeButton(), fakeButton(), ], ), ], ), ), ], ), ); } // Fake buttons Widget fakeButton() { return GestureDetector( onTap: () => setState(() => showSidebar = !showSidebar), child: SizedBox( height: 35, width: 35, child: Stack( children: const [ Icon( Icons.circle, color: Colors.green, size: 35.0, ), Align( alignment: Alignment.center, child: Text( 'HIDE', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 9.0, ), ), ), ], ), ), ); } }
方案说明
AnimatedContainer是通用动画组件,可以完美适配Row的线性布局,不会触发ParentDataWidget错误- 设置和侧边栏完全一致的
duration和curve,保证两者动画同步 - 透明背景不影响页面视觉,同时为侧边栏预留出对应的布局空间
内容的提问来源于stack exchange,提问作者RobbB
相关产品推荐
相关产品推荐

