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
相关产品推荐
相关产品推荐

