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

求助:实现Flutter可展开式GridView图片画廊功能

实现Flutter staggered网格图片点击展开显示额外信息的方案

核心思路是通过状态管理控制每个网格项的展开/收起状态,结合动态调整网格项的尺寸来展示额外信息,以下是完整的实现方案:

1. 确保依赖正确

在pubspec.yaml中添加flutter_staggered_grid_view依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_staggered_grid_view: ^0.7.0 # 使用最新版本

2. 完整实现代码

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

// 定义图片数据模型
class GalleryItem {
  final String imageUrl;
  final String title;
  final String description;

  GalleryItem({
    required this.imageUrl,
    required this.title,
    required this.description,
  });
}

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

  @override
  State<ExpandableGallery> createState() => _ExpandableGalleryState();
}

class _ExpandableGalleryState extends State<ExpandableGallery> {
  // 模拟画廊数据
  final List<GalleryItem> _galleryItems = [
    GalleryItem(
      imageUrl: 'https://picsum.photos/200/300?random=1',
      title: '山间风景',
      description: '这是一张拍摄于阿尔卑斯山脉的风景照,拍摄时间为2023年秋季',
    ),
    GalleryItem(
      imageUrl: 'https://picsum.photos/200/250?random=2',
      title: '城市夜景',
      description: '繁华都市的夜晚,霓虹灯光勾勒出建筑的轮廓',
    ),
    GalleryItem(
      imageUrl: 'https://picsum.photos/200/350?random=3',
      title: '海边日落',
      description: '夕阳洒在海面上,波光粼粼的海面格外迷人',
    ),
    GalleryItem(
      imageUrl: 'https://picsum.photos/200/280?random=4',
      title: '森林小径',
      description: '幽静的森林小径,充满了自然的宁静与生机',
    ),
  ];

  // 记录每个item的展开状态,key为item索引
  final Map<int, bool> _expandedStates = {};

  @override
  void initState() {
    super.initState();
    // 初始化所有item为收起状态
    for (int i = 0; i < _galleryItems.length; i++) {
      _expandedStates[i] = false;
    }
  }

  // 切换展开/收起状态
  void _toggleExpand(int index) {
    setState(() {
      _expandedStates[index] = !_expandedStates[index]!;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('可展开图片画廊')),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: StaggeredGridView.countBuilder(
          crossAxisCount: 2,
          itemCount: _galleryItems.length,
          itemBuilder: (context, index) {
            final item = _galleryItems[index];
            final isExpanded = _expandedStates[index]!;
            return GestureDetector(
              onTap: () => _toggleExpand(index),
              child: AnimatedContainer(
                duration: const Duration(milliseconds: 300),
                margin: const EdgeInsets.all(4.0),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(8.0),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.grey.withOpacity(0.3),
                      blurRadius: 4,
                      offset: const Offset(0, 2),
                    )
                  ],
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    // 图片部分
                    Expanded(
                      child: ClipRRect(
                        borderRadius: BorderRadius.vertical(
                          top: const Radius.circular(8.0),
                          bottom: isExpanded ? Radius.zero : const Radius.circular(8.0),
                        ),
                        child: Image.network(
                          item.imageUrl,
                          fit: BoxFit.cover,
                        ),
                      ),
                    ),
                    // 额外信息部分,展开时显示
                    if (isExpanded)
                      Container(
                        padding: const EdgeInsets.all(12.0),
                        color: Colors.white,
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              item.title,
                              style: const TextStyle(
                                fontSize: 16,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            const SizedBox(height: 8),
                            Text(
                              item.description,
                              style: const TextStyle(fontSize: 14, color: Colors.grey),
                            ),
                          ],
                        ),
                      ),
                  ],
                ),
              ),
            );
          },
          staggeredTileBuilder: (index) {
            final isExpanded = _expandedStates[index]!;
            // 收起时占1列,展开时可自定义高度
            return isExpanded 
                ? const StaggeredTile.extent(1, 400) 
                : const StaggeredTile.fit(1);
          },
          mainAxisSpacing: 4.0,
          crossAxisSpacing: 4.0,
        ),
      ),
    );
  }
}

void main() => runApp(const MaterialApp(home: ExpandableGallery()));

关键实现细节说明

  • 独立状态管理:用Map<int, bool>单独记录每个网格项的展开状态,避免单个状态变量导致所有item同时切换状态。
  • 平滑过渡:使用AnimatedContainer实现展开/收起时的平滑动画,提升交互体验。
  • 动态尺寸调整:通过staggeredTileBuilder根据展开状态调整网格项高度,确保额外信息有足够展示空间。
  • 点击触发逻辑:给每个网格项添加GestureDetector,点击时切换对应item的展开状态。

你可以根据实际需求调整图片加载方式、额外信息的布局样式以及动画时长等参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:16:22