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

Flutter Web可展开侧边栏开发求助:实现带可折叠面板功能遇阻

实现带可展开面板的Flutter Web侧边栏

下面是一个完全自定义的实现方案,能满足你提到的所有需求,逻辑清晰且易于调整:

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(
      title: 'Collapsible Sidebar Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const Scaffold(body: SidebarDemo()),
    );
  }
}

class SidebarDemo extends StatefulWidget {
  const SidebarDemo({super.key});

  @override
  State<SidebarDemo> createState() => _SidebarDemoState();
}

class _SidebarDemoState extends State<SidebarDemo> {
  // 控制侧边栏整体展开/收起
  bool _sidebarExpanded = false;
  // 记录每个面板的展开状态,key为面板标识
  final Map<String, bool> _panelExpanded = {
    'dashboard': false,
    'settings': false,
    'profile': false,
  };

  // 切换侧边栏展开状态
  void _toggleSidebar() {
    setState(() => _sidebarExpanded = !_sidebarExpanded);
  }

  // 切换指定面板的展开状态
  void _togglePanel(String panelKey) {
    setState(() => _panelExpanded[panelKey] = !_panelExpanded[panelKey]!);
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        // 侧边栏主体
        AnimatedContainer(
          duration: const Duration(milliseconds: 300),
          width: _sidebarExpanded ? 260 : 60,
          color: const Color(0xFF2D3748),
          child: Column(
            children: [
              // 顶部展开/收起按钮
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 16),
                child: IconButton(
                  icon: Icon(
                    _sidebarExpanded ? Icons.arrow_back : Icons.menu,
                    color: Colors.white,
                  ),
                  onPressed: _toggleSidebar,
                ),
              ),
              const SizedBox(height: 20),
              // 可展开面板列表(仅侧边栏展开时显示)
              if (_sidebarExpanded)
                Expanded(
                  child: ListView(
                    children: [
                      _buildExpandablePanel(
                        key: 'dashboard',
                        icon: Icons.dashboard,
                        title: '仪表盘',
                        content: const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('概览', style: TextStyle(color: Colors.white70)),
                              SizedBox(height: 8),
                              Text('实时数据', style: TextStyle(color: Colors.white70)),
                              SizedBox(height: 8),
                              Text('报表分析', style: TextStyle(color: Colors.white70)),
                            ],
                          ),
                        ),
                      ),
                      _buildExpandablePanel(
                        key: 'settings',
                        icon: Icons.settings,
                        title: '系统设置',
                        content: const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('账号设置', style: TextStyle(color: Colors.white70)),
                              SizedBox(height: 8),
                              Text('权限管理', style: TextStyle(color: Colors.white70)),
                              SizedBox(height: 8),
                              Text('通知设置', style: TextStyle(color: Colors.white70)),
                            ],
                          ),
                        ),
                      ),
                      _buildExpandablePanel(
                        key: 'profile',
                        icon: Icons.person,
                        title: '个人中心',
                        content: const Padding(
                          padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('基本信息', style: TextStyle(color: Colors.white70)),
                              SizedBox(height: 8),
                              Text('修改密码', style: TextStyle(color: Colors.white70)),
                              SizedBox(height: 8),
                              Text('安全验证', style: TextStyle(color: Colors.white70)),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
            ],
          ),
        ),
        // 主内容区域
        Expanded(
          child: Container(
            color: const Color(0xFFF7FAFC),
            alignment: Alignment.center,
            child: const Text('主内容区域'),
          ),
        ),
      ],
    );
  }

  // 构建单个可展开面板
  Widget _buildExpandablePanel({
    required String key,
    required IconData icon,
    required String title,
    required Widget content,
  }) {
    return Column(
      children: [
        InkWell(
          onTap: () => _togglePanel(key),
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            child: Row(
              children: [
                Icon(icon, color: Colors.white),
                const SizedBox(width: 16),
                Text(title, style: const TextStyle(color: Colors.white, fontSize: 16)),
                const Spacer(),
                Icon(
                  _panelExpanded[key]! ? Icons.expand_less : Icons.expand_more,
                  color: Colors.white,
                ),
              ],
            ),
          ),
        ),
        // 面板内容,根据展开状态显示/隐藏并添加动画
        AnimatedSize(
          duration: const Duration(milliseconds: 200),
          curve: Curves.easeInOut,
          child: _panelExpanded[key]! ? content : const SizedBox(height: 0),
        ),
        const Divider(color: Colors.white24, height: 1),
      ],
    );
  }
}

关键逻辑说明

  1. 侧边栏状态控制:用_sidebarExpanded变量控制侧边栏宽度,点击顶部菜单图标切换状态,通过AnimatedContainer实现平滑宽度过渡。
  2. 面板展开状态管理:用_panelExpanded这个Map记录每个面板的展开状态,点击面板头部时切换对应键的值。
  3. 面板内容动画:使用AnimatedSize实现面板展开/收起的高度过渡动画,比直接用Visibility更流畅。
  4. Flutter Web适配:侧边栏宽度设置适配Web端,点击区域用InkWell保证鼠标点击反馈,也可自行添加MouseRegion实现悬停高亮效果。

如果之前用第三方包出现问题,大概率是包的状态管理和业务逻辑冲突,自定义实现完全可控,你可以根据需求修改样式、添加更多面板或调整动画参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:28:10