You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter中如何基于folding_cell插件实现多折叠卡片?

解决folding_cell插件添加多个折叠卡片的问题

我看你已经尝试用folding_cell插件实现折叠卡片,现在想要添加多个折叠卡片的功能,刚好你已经有了单个卡片和ListView的基础代码,我来帮你完善这两种场景下的实现方案,同时修复一些版本兼容的小问题:

场景1:在容器中添加多个独立折叠卡片

单个折叠卡片用了GlobalKey来控制状态,多个卡片的话需要给每个卡片分配独立的key,我们可以用一个List来管理这些key,这样就能分别控制每个卡片的折叠状态:

class MultiFoldingCellDemo extends StatelessWidget {
  // 为每个折叠卡片生成独立的GlobalKey
  final List<GlobalKey<SimpleFoldingCellState>> _cellKeys = List.generate(3, (index) => GlobalKey<SimpleFoldingCellState>());

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Color(0xFF2e282a),
      padding: const EdgeInsets.symmetric(vertical: 10),
      child: Column(
        children: List.generate(3, (index) {
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
            child: SimpleFoldingCell(
              key: _cellKeys[index],
              frontWidget: _buildFrontWidget(index),
              innerTopWidget: _buildInnerTopWidget(index),
              innerBottomWidget: _buildInnerBottomWidget(index),
              cellSize: Size(MediaQuery.of(context).size.width, 125),
              padding: EdgeInsets.all(15),
              animationDuration: Duration(milliseconds: 300),
              borderRadius: 10,
              onOpen: () => print('cell $index opened'),
              onClose: () => print('cell $index closed'),
            ),
          );
        }),
      ),
    );
  }

  Widget _buildFrontWidget(int index) {
    return Container(
      color: Color(0xFFffcd3c),
      alignment: Alignment.center,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text("CARD - $index", style: TextStyle(
              color: Color(0xFF2e282a),
              fontFamily: 'OpenSans',
              fontSize: 20.0,
              fontWeight: FontWeight.w800)),
          FlatButton(
            onPressed: () => _cellKeys[index].currentState?.toggleFold(),
            child: Text("Open"),
            textColor: Colors.white,
            color: Colors.indigoAccent,
            splashColor: Colors.white.withOpacity(0.5),
          )
        ],
      ),
    );
  }

  Widget _buildInnerTopWidget(int index) {
    return Container(
      color: Color(0xFFff9234),
      alignment: Alignment.center,
      child: Text("TITLE - $index", style: TextStyle(
          color: Color(0xFF2e282a),
          fontFamily: 'OpenSans',
          fontSize: 20.0,
          fontWeight: FontWeight.w800)));
  }

  Widget _buildInnerBottomWidget(int index) {
    return Container(
      color: Color(0xFFecf2f9),
      alignment: Alignment.bottomCenter,
      child: Padding(
        padding: EdgeInsets.only(bottom: 10),
        child: FlatButton(
          onPressed: () => _cellKeys[index].currentState?.toggleFold(),
          child: Text("Close"),
          textColor: Colors.white,
          color: Colors.indigoAccent,
          splashColor: Colors.white.withOpacity(0.5),
        ),
      ),
    );
  }
}

场景2:优化ListView中的多折叠卡片实现

你现有的ListView示例已经支持多卡片,但ancestorStateOfType在Flutter 2.12+版本已经被废弃,我帮你替换成最新的findAncestorStateOfType方法,确保代码能正常运行:

class FoldingCellListViewDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Color(0xFF2e282a),
      child: ListView.builder(
          itemCount: 100,
          padding: const EdgeInsets.symmetric(vertical: 10),
          itemBuilder: (context, index) {
            return Padding(
              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
              child: SimpleFoldingCell(
                  frontWidget: _buildFrontWidget(index),
                  innerTopWidget: _buildInnerTopWidget(index),
                  innerBottomWidget: _buildInnerBottomWidget(index),
                  cellSize: Size(MediaQuery.of(context).size.width, 125),
                  padding: EdgeInsets.all(15),
                  animationDuration: Duration(milliseconds: 300),
                  borderRadius: 10,
                  onOpen: () => print('$index cell opened'),
                  onClose: () => print('$index cell closed')),
            );
          }),
    );
  }

  Widget _buildFrontWidget(int index) {
    return Builder(
      builder: (BuildContext context) {
        return Container(
          color: Color(0xFFffcd3c),
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text("CARD - $index", style: TextStyle(
                  color: Color(0xFF2e282a),
                  fontFamily: 'OpenSans',
                  fontSize: 20.0,
                  fontWeight: FontWeight.w800)),
              FlatButton(
                onPressed: () {
                  // 替换为Flutter新版本支持的findAncestorStateOfType
                  SimpleFoldingCellState? foldingCellState = context.findAncestorStateOfType<SimpleFoldingCellState>();
                  foldingCellState?.toggleFold();
                },
                child: Text("Open"),
                textColor: Colors.white,
                color: Colors.indigoAccent,
                splashColor: Colors.white.withOpacity(0.5),
              )
            ],
          ),
        );
      },
    );
  }

  Widget _buildInnerTopWidget(int index) {
    return Container(
      color: Color(0xFFff9234),
      alignment: Alignment.center,
      child: Text("TITLE - $index", style: TextStyle(
          color: Color(0xFF2e282a),
          fontFamily: 'OpenSans',
          fontSize: 20.0,
          fontWeight: FontWeight.w800)));
  }

  Widget _buildInnerBottomWidget(int index) {
    return Builder(builder: (context) {
      return Container(
        color: Color(0xFFecf2f9),
        alignment: Alignment.bottomCenter,
        child: Padding(
          padding: EdgeInsets.only(bottom: 10),
          child: FlatButton(
            onPressed: () {
              SimpleFoldingCellState? foldingCellState = context.findAncestorStateOfType<SimpleFoldingCellState>();
              foldingCellState?.toggleFold();
            },
            child: Text("Close"),
            textColor: Colors.white,
            color: Colors.indigoAccent,
            splashColor: Colors.white.withOpacity(0.5),
          ),
        ),
      );
    });
  }
}

几个关键注意点

  • 独立状态管理:非列表场景用独立的GlobalKey列表控制每个卡片;列表场景用Builder包裹卡片内容,结合findAncestorStateOfType获取当前卡片的状态,确保每个卡片的折叠操作互不影响
  • 布局适配:给卡片添加适当的内外边距,避免卡片之间过于拥挤,同时确保cellSize的宽度适配屏幕宽度
  • 动态内容扩展:可以根据index从数据源(比如列表数组)中获取动态内容,替换示例中的静态文本,实现更实用的多卡片效果

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

火山引擎 最新活动