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

Flutter有没有简单方法可读取指定文件夹内的图片并随机展示?

实现方案

步骤1:配置资源路径

首先把4套主题的图片文件夹统一放在assets目录下,目录结构如下:

assets/
  ├── bluethemedimages/
  │   ├── xxx.jpg
  │   ├── yyy.jpg
  │   └── ...
  ├── yellowthemedimages/
  ├── greenthemedimages/
  └── graythemedimages/

在pubspec.yaml中直接配置文件夹路径即可,不需要逐个添加图片资源:

flutter:
  assets:
    - assets/bluethemedimages/
    - assets/yellowthemedimages/
    - assets/greenthemedimages/
    - assets/graythemedimages/

步骤2:编写随机图片获取逻辑

通过Flutter内置的资产清单能力直接筛选对应文件夹下的所有图片,无需手动维护图片路径列表:

import 'dart:math';
import 'package:flutter/services.dart';

// 传入主题文件夹名称,返回随机的AssetImage
Future<AssetImage> getRandomThemeImage(String themeFolder) async {
  // 加载所有资产清单
  final manifest = await AssetManifest.loadFromAssetBundle(rootBundle);
  final allAssets = manifest.listAssets();
  // 筛选对应主题文件夹下的所有图片资源
  final themeImages = allAssets.where((path) => path.startsWith("assets/$themeFolder/")).toList();
  // 随机抽取一张
  final randomIndex = Random().nextInt(themeImages.length);
  return AssetImage(themeImages[randomIndex]);
}

如果使用的Flutter版本低于3.10,使用兼容写法即可,需要额外导入dart:convert:

Future<AssetImage> getRandomThemeImage(String themeFolder) async {
  final manifestContent = await rootBundle.loadString('AssetManifest.json');
  final Map<String, dynamic> manifestMap = json.decode(manifestContent);
  final themeImages = manifestMap.keys.where((path) => path.startsWith("assets/$themeFolder/")).toList();
  final randomIndex = Random().nextInt(themeImages.length);
  return AssetImage(themeImages[randomIndex]);
}

步骤3:页面逻辑实现

通过FutureBuilder加载图片,点击主题按钮后切换文件夹参数触发重新加载即可:

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

  @override
  State<ThemeImagePage> createState() => _ThemeImagePageState();
}

class _ThemeImagePageState extends State<ThemeImagePage> {
  String currentThemeFolder = "bluethemedimages";

  Future<AssetImage> getRandomThemeImage(String themeFolder) async {
    final manifest = await AssetManifest.loadFromAssetBundle(rootBundle);
    final allAssets = manifest.listAssets();
    final themeImages = allAssets.where((path) => path.startsWith("assets/$themeFolder/")).toList();
    final randomIndex = Random().nextInt(themeImages.length);
    return AssetImage(themeImages[randomIndex]);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<AssetImage>(
        future: getRandomThemeImage(currentThemeFolder),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return const Center(child: CircularProgressIndicator());
          }
          return Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: snapshot.data!,
                fit: BoxFit.cover,
              ),
            ),
            child: Stack(
              children: [
                Positioned(
                  bottom: 50,
                  left: 20,
                  right: 20,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: [
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
                        onPressed: () => setState(() => currentThemeFolder = "bluethemedimages"),
                        child: const Text("蓝色"),
                      ),
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(backgroundColor: Colors.yellow),
                        onPressed: () => setState(() => currentThemeFolder = "yellowthemedimages"),
                        child: const Text("黄色"),
                      ),
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
                        onPressed: () => setState(() => currentThemeFolder = "greenthemedimages"),
                        child: const Text("绿色"),
                      ),
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(backgroundColor: Colors.grey),
                        onPressed: () => setState(() => currentThemeFolder = "graythemedimages"),
                        child: const Text("灰色"),
                      ),
                    ],
                  ),
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

如果需要优化性能,可以在页面初始化时预加载所有主题的图片路径列表,避免每次点击都重新读取资产清单。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:57:04