#image #flutter #pdf #sharedpreferences
#изображение #flutter #PDF #sharedpreferences
Вопрос:
Мне нужно загрузить изображение из SharedPreferences в документ pdf. Изображение загружается нормально при обычном использовании, но я не знаю, как заставить его загружаться в PDF. Когда я пытаюсь загрузить его как обычное изображение, я получаю «Необработанное исключение: тип «Изображение» не является подтипом типа «PdfImage»»
Вот как я обычно его использую.
import 'package:flutter/material.dart';
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
import 'package:image_picker/image_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:MyApp/SharedPrefUtility.dart';
Future<void> initSettings() async {
await Settings.init(
cacheProvider: SharePreferenceCache(),
);
}
class ProfilePage extends StatefulWidget {
@override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
Image logo;
pickImage(ImageSource source) async {
final _image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (_image != null) {
setState(() {
logo = Image.file(_image);
});
ImageSharedPrefs.saveImageToPrefs(
ImageSharedPrefs.base64String(_image.readAsBytesSync()));
} else {
print('Error picking image!');
}
}
loadImageFromPrefs() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final imageKeyValue = prefs.getString(IMAGE_KEY);
if (imageKeyValue != null) {
final imageString = await ImageSharedPrefs.loadImageFromPrefs();
setState(() {
logo = ImageSharedPrefs.imageFrom64BaseString(imageString);
});
}
}
@override
void initState() {
super.initState();
loadImageFromPrefs();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text('Profile Settings'),
),
body: Center(
child: ListView(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ClipRect(
child: Container(
width: 300,
height: 300,
child: logo == null ? Text('No image selected.') : logo,
),
),
RaisedButton(
onPressed: () {
pickImage(ImageSource.gallery);
},
child: Text('Pick Company Logo'),
),
],
),
],
),
),
);
}
}
С помощью SharedPrefUtility.dart
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/widgets.dart';
import 'package:shared_preferences/shared_preferences.dart';
const IMAGE_KEY = 'IMAGE_KEY';
class ImageSharedPrefs {
static Future<bool> saveImageToPrefs(String value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return await prefs.setString(IMAGE_KEY, value);
}
static Future<String> loadImageFromPrefs() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(IMAGE_KEY);
}
static String base64String(Uint8List data) {
return base64Encode(data);
}
static imageFrom64BaseString(String base64String) {
return Image.memory(
base64Decode(base64String),
fit: BoxFit.contain,
);
}
}
Любые предложения были бы замечательными.
Ответ №1:
davey06 дал ответ на GitHub
final imageString = await ImageSharedPrefs.loadImageFromPrefs();
// Create a PDF document.
final document = pw.Document();
// Add page to the PDF
document.addPage(pw.Page(build: (context) {
return pw.Center(
child: pw.Image(
PdfImage.file(document.document, bytes: base64Decode(imageString)),
),
);
}));
// Return the PDF file content
return document.save();
Комментарии:
1. Вы должны пометить свой собственный ответ как правильный, чтобы он не отображался как неотвеченный для других
Ответ №2:
«Необработанное исключение: тип «Изображение» не является подтипом типа «PdfImage»» — в нем говорится, что вам нужно преобразовать изображение в PdfImage
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart ' as pw;
pdf = pw.Document();
PdfImage pdfImage = PdfImage.fromImage(pdf.document, image: logo);
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a4,
build: (context) {
return pw.Image(arcPdfImage, fit: pw.BoxFit.contain);
},
),
);
Комментарии:
1. Привет. Спасибо за быстрый ответ. Я все еще не могу заставить его работать. У меня уже есть рабочий PDF-файл с изображениями из папки assets и из кэша, и все работает на 100%. Мне просто нужно также загрузить изображение из SharedPreferences. Я думал, что это должно быть что-то вроде final logo = ImageSharedPrefs.imageFrom64BaseString(ожидает ImageSharedPrefs.loadImageFromPrefs()); Но я получаю указанную ошибку.
Ответ №3:
Я использую изображения, взятые из моих ресурсов, для создания PDF таким образом:
PdfImage _logo = PdfImage.file(
doc.document,
bytes: (await rootBundle.load('assets/client-logo.png')).buffer.asUint8List(),
);
//later, during widget tree creation
pw.Image(_logo, width: 180);
Это не совсем то, что вы делаете, но я думаю, что это достаточно близко. Класс PdfImage может принимать в качестве входных данных любой Uint8List для bytes
аргумента, поэтому вы должны иметь возможность использовать тот же ввод, который вы используете для base64String
метода, который вы определили для ImageSharedPrefs
Комментарии:
1. Привет. Спасибо. Я использую это для изображений из моей папки assets, я также загружаю изображение из кэша. Все работает нормально, кроме изображения из общих настроек. rootBundle можно использовать только для изображений, которые существуют, так сказать, до запуска приложения. Изображение, которое находится в общих настройках, имеет строковый формат, поэтому я пытаюсь преобразовать его так, чтобы pdf мог его прочитать.
2. @Fenix вы пытались показать изображение из настроек в стандартном виджете Flutter, например
Image
? Если вы можете управлять этим, скажем, с помощью именованного конструктораImage.memory()
, который принимает в качестве входных данных Uint8List, вы должны иметь возможность использовать тот же ввод дляPdfImage
3. Привет. Да, я пытаюсь это сделать, но пока никаких результатов. Я уверен, что должен быть способ сделать это, я просто еще не нашел его.