Flutter:实现AnimatedPositioned侧边栏右侧定位及点击隐藏动画
解决Flutter侧边栏右侧定位与滑入滑出问题
问题核心
你的代码中AnimatedPositioned缺少必要的位置与尺寸约束,导致添加位置属性时触发约束错误;同时内容区域的占位逻辑可简化,用更流畅的动画方式实现宽度自适应。
修改后的完整代码
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: 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) { final screenWidth = MediaQuery.of(context).size.width; final sidebarWidth = 43.0; return SafeArea( child: Stack( children: [ // 主内容区域:随侧边栏状态平滑调整宽度 AnimatedContainer( duration: const Duration(milliseconds: 500), curve: Curves.ease, width: showSidebar ? screenWidth - sidebarWidth : screenWidth, child: SingleChildScrollView( child: Column( children: [ Container( width: double.infinity, height: 700, color: Colors.red, ), Container( width: double.infinity, height: 700, color: Colors.yellow, ), ], ), ), ), // 侧边栏:固定右侧,滑入滑出动画 AnimatedPositioned( right: showSidebar ? 0 : -sidebarWidth, top: 0, height: MediaQuery.of(context).size.height, width: sidebarWidth, curve: Curves.ease, duration: const Duration(milliseconds: 500), child: Container( color: Colors.blue, child: Column( mainAxisAlignment: MainAxisAlignment.start, children: const [ SizedBox(height: 120.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(), ], ), ], ), ), ], ), ); } Widget fakeButton() { return GestureDetector( onTap: () => setState(() => showSidebar = !showSidebar), child: const SizedBox( height: 35, width: 35, child: Stack( children: [ 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, ), ), ), ], ), ), ); } }
关键修改说明
- 补全AnimatedPositioned约束:添加
right(控制侧边栏位置,显示时贴右侧,隐藏时滑出屏幕)、top、height,明确侧边栏的位置与尺寸,解决约束错误问题。 - 优化主内容区域:用
AnimatedContainer替代原Row+占位SizedBox逻辑,让内容宽度随侧边栏状态平滑过渡,满足全屏填充需求。 - 简化状态切换:将按钮点击的状态切换逻辑简化为
showSidebar = !showSidebar,减少冗余代码。 - 调整布局层级:确保控制按钮在Stack最上层,避免被侧边栏或内容区域遮挡。
内容的提问来源于stack exchange,提问作者RobbB
相关产品推荐
相关产品推荐

