Flutter:实现嵌套容器内子容器点击右侧展开的方法
Flutter 实现点击容器右侧展开效果
实现思路
- 用
StatefulWidget维护当前选中的容器索引,初始设为-1(无选中状态) - 给每个绿色容器绑定点击事件,点击时更新选中索引
- 构建容器时,根据是否为当前选中项,动态调整容器宽度(或切换展开/收起的布局结构)
完整代码示例
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( home: Scaffold( appBar: AppBar(title: const Text('点击展开容器')), body: const ExpandableContainerList(), ), ); } } class ExpandableContainerList extends StatefulWidget { const ExpandableContainerList({super.key}); @override State<ExpandableContainerList> createState() => _ExpandableContainerListState(); } class _ExpandableContainerListState extends State<ExpandableContainerList> { // 记录当前选中的容器索引,-1表示未选中任何容器 int _selectedIndex = -1; // 模拟5个容器的数据源 final List<String> _items = List.generate(5, (index) => '容器 ${index + 1}'); @override Widget build(BuildContext context) { return Container( color: const Color(0xFFE0E5EC), // 灰蓝色背景 padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8), child: ListView.builder( itemCount: _items.length, itemBuilder: (context, index) { return GestureDetector( onTap: () { setState(() { // 点击切换选中状态:若当前是选中项则取消,否则设置为当前索引 _selectedIndex = _selectedIndex == index ? -1 : index; }); }, child: AnimatedContainer( duration: const Duration(milliseconds: 300), margin: const EdgeInsets.only(bottom: 12), height: 80, // 根据选中状态动态设置宽度 width: _selectedIndex == index ? MediaQuery.of(context).size.width * 0.9 // 展开宽度 : MediaQuery.of(context).size.width * 0.7, // 收起宽度 decoration: BoxDecoration( color: Colors.green, borderRadius: BorderRadius.circular(8), boxShadow: const [ BoxShadow( color: Colors.black12, blurRadius: 4, offset: Offset(2, 2), ) ], ), alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsets.only(left: 16), child: Text( _items[index], style: const TextStyle(color: Colors.white, fontSize: 18), ), ), // 展开时显示额外元素(示例用箭头图标) if (_selectedIndex == index) const Padding( padding: EdgeInsets.only(right: 16), child: Icon(Icons.arrow_forward, color: Colors.white), ), ], ), ), ); }, ), ); } }
关键细节说明
- 状态管理:通过
_selectedIndex控制容器的展开状态,点击时调用setState触发UI更新 - 平滑过渡:使用
AnimatedContainer替代普通Container,让宽度变化带有动画效果,提升交互体验 - 动态布局:利用
MediaQuery获取屏幕宽度,根据选中状态设置不同的容器宽度,实现右侧展开的视觉效果 - 扩展能力:如果需要展开后显示更多内容,可将容器的子组件替换为包含展开内容的布局,配合
AnimatedSwitcher实现内容切换动画
内容的提问来源于stack exchange,提问作者Vaishnav k
相关产品推荐
相关产品推荐

