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

如何实现Flutter中点击展开的可扩展容器及滚动TabView?

Flutter 实现点击展开带TabView的容器布局

可以用AnimatedContainer结合TabController来实现这个需求,ExpansionTile因为内部布局的限制,很难适配带可滚动TabView的场景,而AnimatedContainer能更灵活地控制容器高度变化,同时配合Tab组件实现标签页功能。

完整实现代码

import 'package:flutter/material.dart';

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

  @override
  State<UserProfilePage> createState() => _UserProfilePageState();
}

class _UserProfilePageState extends State<UserProfilePage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  bool _isExpanded = false;
  final double _collapsedHeight = 120; // 折叠状态下的容器高度
  final double _expandedHeight = 400; // 展开状态下的容器高度

  @override
  void initState() {
    super.initState();
    // 初始化Tab控制器,这里设置为2个标签页
    _tabController = TabController(length: 2, vsync: this);
  }

  @override
  void dispose() {
    // 销毁控制器避免内存泄漏
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("用户ID页面")),
      body: Column(
        children: [
          // 可点击的展开容器
          GestureDetector(
            onTap: () => setState(() => _isExpanded = !_isExpanded),
            child: AnimatedContainer(
              duration: const Duration(milliseconds: 300),
              height: _isExpanded ? _expandedHeight : _collapsedHeight,
              margin: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: const [BoxShadow(color: Colors.grey, blurRadius: 4, offset: Offset(0, 2))],
              ),
              child: Column(
                children: [
                  // 折叠/展开都显示的头部
                  const Padding(
                    padding: EdgeInsets.symmetric(horizontal: 16, vertical: 20),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          "用户基本信息",
                          style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                        ),
                        // 可选:添加展开/收起的箭头图标
                        Icon(Icons.expand_more),
                      ],
                    ),
                  ),
                  // 展开状态下显示Tab区域
                  if (_isExpanded)
                    Expanded(
                      child: Column(
                        children: [
                          TabBar(
                            controller: _tabController,
                            labelColor: Colors.blue,
                            unselectedLabelColor: Colors.grey,
                            tabs: const [
                              Tab(text: "数据列表1"),
                              Tab(text: "数据列表2"),
                            ],
                          ),
                          Expanded(
                            child: TabBarView(
                              controller: _tabController,
                              children: [
                                // 第一个Tab的可滚动内容
                                SingleChildScrollView(
                                  padding: const EdgeInsets.all(16),
                                  child: Column(
                                    children: List.generate(20, (index) {
                                      return Padding(
                                        padding: const EdgeInsets.only(bottom: 12),
                                        child: Text("数据1 - 条目 $index", style: const TextStyle(fontSize: 16)),
                                      );
                                    }),
                                  ),
                                ),
                                // 第二个Tab的可滚动内容
                                SingleChildScrollView(
                                  padding: const EdgeInsets.all(16),
                                  child: Column(
                                    children: List.generate(15, (index) {
                                      return Padding(
                                        padding: const EdgeInsets.only(bottom: 12),
                                        child: Text("数据2 - 条目 $index", style: const TextStyle(fontSize: 16)),
                                      );
                                    }),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                ],
              ),
            ),
          ),
          // 页面剩余内容
          const Expanded(
            child: Center(child: Text("页面其他内容区域")),
          ),
        ],
      ),
    );
  }
}

关键实现要点

  • AnimatedContainer:通过切换_isExpanded状态来改变容器高度,配合duration参数实现平滑的展开/收起动画。
  • TabController:需要混入SingleTickerProviderStateMixin来提供动画支持,管理TabBar和TabBarView的同步切换。
  • 可滚动Tab内容:在TabBarView的子组件中使用SingleChildScrollView,确保内容超过容器高度时可以滚动。
  • 交互优化:可以在头部添加箭头图标,让用户更直观地知道这是可展开的容器,点击整个容器或单独图标都能触发状态切换。

如果需要动态调整展开后的高度,可以用LayoutBuilder获取容器的可用宽度,再结合内容的实际高度来计算,避免固定高度带来的适配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:15:49