flutter - 在 Flutter 中从图库中保存 ImagePicker 图像
问题描述
与往常一样,这些最简单的解决方案对我来说是最难解决的。我有 ImagePicker 函数可以从图库中获取图像并将其设置为背景。下面的代码完美运行,但图像没有保存,所以每次重新启动后,它都不存在。这是代码:
Future _getImage() async {
final picker = ImagePicker();
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
print('_image: $_image');
} else {
print('No image selected');
}
});
}
所以我的问题是如何保存图像以使其永久保存并在重新启动后持续存在,我已经尝试了一切(设置和保存路径等),但由于某种原因无法让它工作。希望解决方案很简单。我的理解是它应该保存到设备的本地存储中,在这种情况下是模拟器,但它当然应该适用于每个设备。
解决方案
您可以将用户从图库中挑选的图像保存到应用程序目录。然后,使用此图像从本地存储中显示。
使用path_provider获取目录路径
Directory appDocDir = await getApplicationDocumentsDirectory(); String appDocPath = appDocDir.path;
将图像保存到您的目录
final picker = ImagePicker(); final pickedFile = await picker.getImage(source: ImageSource.gallery); if (pickedFile == null) return; _image = File(pickedFile.path); final fileName = 'background_image'; final File localImage = await _image.copy('${widget.appDocPath}/$fileName');
使用小部件树中的图像
Image image; var hasLocalImage = File('${widget.appDocPath}/background_image').existsSync(); if (hasLocalImage) { var bytes = File('${widget.appDocPath}/background_image').readAsBytesSync(); image = Image.memory(bytes); }
完整的工作示例:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SplashScreen(),
);
}
}
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
String appDocPath;
Future<void> getApplicationDirectoryPath() async {
Directory appDocDir = await getApplicationDocumentsDirectory();
appDocPath = appDocDir.path;
}
@override
initState() {
getApplicationDirectoryPath().then((_) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext context) => Home(
appDocPath,
)));
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
class Home extends StatefulWidget {
final String appDocPath;
Home(this.appDocPath);
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
File _image;
@override
initState() {
super.initState();
}
Future _getImage() async {
final picker = ImagePicker();
final pickedFile = await picker.getImage(source: ImageSource.gallery);
if (pickedFile == null) return;
_image = File(pickedFile.path);
final fileName = 'background_image';
final File localImage = await _image.copy('${widget.appDocPath}/$fileName');
setState(() {
});
}
@override
Widget build(BuildContext context) {
Image image;
var hasLocalImage =
File('${widget.appDocPath}/background_image').existsSync();
if (hasLocalImage) {
var bytes =
File('${widget.appDocPath}/background_image').readAsBytesSync();
image = Image.memory(bytes);
}
return new Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
_getImage();
},
),
body: (File('${widget.appDocPath}/background_image').existsSync())
? Center(
child: image,
)
: Text('NO PICTURE HAS BEEN SELECTED NOW OR IN THE PAST'));
}
}