You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

关键修改说明

  1. 补全AnimatedPositioned约束:添加right(控制侧边栏位置,显示时贴右侧,隐藏时滑出屏幕)、top、height,明确侧边栏的位置与尺寸,解决约束错误问题。
  2. 优化主内容区域:用AnimatedContainer替代原Row+占位SizedBox逻辑,让内容宽度随侧边栏状态平滑过渡,满足全屏填充需求。
  3. 简化状态切换:将按钮点击的状态切换逻辑简化为showSidebar = !showSidebar,减少冗余代码。
  4. 调整布局层级:确保控制按钮在Stack最上层,避免被侧边栏或内容区域遮挡。

内容的提问来源于stack exchange,提问作者RobbB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:35:11