【问题标题】:Load image from sharedPreferences to pdf in Flutter在 Flutter 中将图像从 sharedPreferences 加载到 pdf
【发布时间】:2021-02-24 04:56:22
【问题描述】:

我需要将图像从 sharedPreferences 加载到 pdf 文档。 正常使用时图像正常加载,但我不知道如何使其加载到 pdf 中。 当我尝试像普通图像一样加载它时,我得到“未处理的异常:类型'Image'不是'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,
    );
  }
}

任何建议都会很棒。

【问题讨论】:

    标签: image flutter pdf sharedpreferences


    【解决方案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();
    

    https://github.com/DavBfr/dart_pdf/issues/477

    【讨论】:

    • 您应该将自己的答案标记为正确的答案,这样其他人就不会显示为未回答
    【解决方案2】:

    “未处理的异常:'Image' 类型不是'PdfImage' 类型的子类型” - 它表示您需要将 Image 转换为 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);
        },
      ),
    );
    

    【讨论】:

    • 嗨。感谢您的快速回复。我仍然无法让它工作。我已经有一个工作 pdf 文件,其中包含来自 assets 文件夹和 chache 的图像,并且一切正常 100%。我也只需要从 sharedPreferences 加载图像。我在想它应该类似于 final logo = ImageSharedPrefs.imageFrom64BaseString(await 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 类可以将 bytes 参数的任何 Uint8List 作为输入,因此您应该能够使用与为 ImageSharedPrefs 定义的 base64String 方法相同的输入

    【讨论】:

    • 嗨。谢谢。我确实将它用于我的资产文件夹中的图像,我还从缓存中加载图像。除了共享首选项中的图像外,一切都很好。 rootBundle 只能用于应用程序启动之前存在的图像。共享首选项中的图像是字符串格式,所以我尝试对其进行转换,以便 pdf 可以读取它。
    • @Fenix 您是否尝试过在标准 Flutter 小部件中显示首选项中的图像,例如 Image?如果你能做到这一点,比方说,通过使用命名构造函数Image.memory(),它将一个Uint8List作为输入,你应该能够为PdfImage使用相同的输入
    • 嗨。是的,我正在尝试这样做,但还没有结果。我确定一定有办法做到这一点,我只是还没有找到。
    猜你喜欢
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 2018-05-22
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    相关资源
    最近更新 更多