Afur / flutter_html_to_pdf

Flutter plugin for generating PDF files from HTML
MIT License
69 stars 126 forks source link

CSS not rendering properly in flutter_html_to_pdf on iOS devices #83

Closed jamalbtl closed 10 months ago

jamalbtl commented 10 months ago

I am relatively new to Flutter and am currently working with the flutter_html_to_pdf dependency. Everything works fine on Android devices, but I am encountering an issue specifically on iOS devices. The problem is related to CSS rendering, and the styling is not applied correctly when using flutter_html_to_pdf on iOS. Environment: Flutter version: 3.13.6 Xcode version: 15 When attempting to convert HTML to PDF using flutter_html_to_pdf on iOS devices, the CSS styling is not rendered as expected. This issue is observed only on iOS devices, and Android devices are not affected. CONTROLLER

import 'dart:io';
import 'package:alfnr/app/helpers/component/custom_snackbar.dart';
import 'package:alfnr/app/routes/app_pages.dart';
import 'package:flutter_html_to_pdf/flutter_html_to_pdf.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

class ReceiptPreviewController extends GetxController {
  RxString generatedPdfFilePath = "".obs;
  RxString htmlContent = "".obs;
  RxString receiptNo = "".obs;

  @override
  void onInit() {
    showInvoice();
    super.onInit();
  }

  showInvoice() {
    var data = Get.arguments['receipt_data'];
    if (Get.arguments != null) {
      htmlContent.value = data['data']['content'];
      receiptNo.value = data['data']['receipt_no'];
      showPdf(htmlContent.value, receiptNo.value);
    } else {
      print("Argument Nulled");
    }
  }

  showPdf(html, receiptNo) async {

    var status = await Permission.storage.status;

    if (status.isGranted) {
      Directory appDocDir = await getApplicationDocumentsDirectory();
      final targetPath = appDocDir.path;
      final targetFileName = receiptNo;
      final generatedPdfFile =
          await FlutterHtmlToPdf.convertFromHtmlContent(html, targetPath, targetFileName);
      generatedPdfFilePath.value = generatedPdfFile.path;
    } else {
      print("Permission Not Granted");
    }
  }

  completed() {
    ShowSnackbar.show(message: 'Receipt Completed');
    Get.offAllNamed(Routes.home);
  }
}

VIEW

import 'package:alfnr/app/modules/receipt/controllers/receipt_preview_controller.dart';
import 'package:alfnr/app/utils/alfnr_icons.dart';
import 'package:alfnr/app/utils/text_style_util.dart';
import 'package:alfnr/generated/locales.g.dart';
import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:share_plus/share_plus.dart';

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

  @override
  State<ReceiptPreview> createState() => _ReceiptPreviewState();
}

class _ReceiptPreviewState extends State<ReceiptPreview> {
  @override
  Widget build(BuildContext context) {
    ReceiptPreviewController controller = Get.put(ReceiptPreviewController());
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(40),
        child: AppBar(
          title: const Text(""),
          titleSpacing: 0,
          centerTitle: false,
          leadingWidth: 50,
          leading: Center(
            child: Material(
              type: MaterialType.transparency,
              child: IconButton(
                onPressed: () => Get.back(),
                icon: const Icon(
                  Alfnr.left,
                  color: Colors.black,
                  size: 17,
                ),
                constraints: const BoxConstraints(maxWidth: 30, minWidth: 30),
                // iconSize: 40,
              ),
            ),
          ),
        ),
      ),
      body: GestureDetector(
        child: SafeArea(
          child: Obx(() {
            controller.generatedPdfFilePath.value;
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 20),
                  child: Text(
                    LocaleKeys.app_Preview.tr,
                    textAlign: TextAlign.start,
                    style: AppTextStyle().getBoldTextStyle(fontSize: 25.sp),
                  ),
                ),
                SizedBox(height: 20.h),
                controller.generatedPdfFilePath.value == ''
                    ? const Center(
                        child: CircularProgressIndicator(),
                      )
                    : Expanded(
                        child: PDFView(
                          filePath: controller.generatedPdfFilePath.value,
                          onPageError: (page, error) {
                            print("VIEW PAGE ERROR");
                            print(error);
                          },
                          onRender: (pages) {
                            print("VIEW RENDER ERROR");
                            print(pages);
                          },
                          onViewCreated: (controller) {
                            print("VIEW CREATED ERROR");
                            print(controller);
                          },
                          onError: (error) {
                            print("VIEW ONErorr ERROR");
                            print(error);
                          },
                        ),
                      ),
                Row(
                  children: [
                    Expanded(
                      child: Container(
                        height: 80,
                        padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
                        color: Colors.white,
                        child: ElevatedButton(
                          onPressed: () async {
                            await Share.shareXFiles([XFile(controller.generatedPdfFilePath.value)],
                                text: 'RECEIPT ATTACHED');
                          },
                          style: ButtonStyle(
                            shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                              RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(20),
                              ),
                            ),
                          ),
                          child: Text(LocaleKeys.app_Share.tr),
                        ),
                      ),
                    ),
                  ],
                ),
                Row(
                  children: [
                    Expanded(
                      child: Container(
                        height: 80,
                        padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
                        color: Colors.white,
                        child: ElevatedButton(
                          onPressed: () {
                            controller.completed();
                          },
                          style: ElevatedButton.styleFrom(
                              backgroundColor: Colors.white,
                              shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(20),
                                  side: const BorderSide(width: 2, color: Colors.blue))),
                          child: const Text(
                            'Complete',
                            style: TextStyle(color: Colors.blue),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            );
          }),
        ),
      ),
    );
  }

  @override
  void dispose() {
    Get.delete<ReceiptPreviewController>();
    super.dispose();
  }
}

Samples are attached. ANDROID RESULT 2024-01-06_21-46-59 . iOS RESULT 2024-01-06_21-47-38 . Please advise on how to resolve this issue or if there are any updates, patches, or recommendations for a fix. Thank you!

raister21 commented 10 months ago

Same issue https://github.com/Afur/flutter_html_to_pdf/issues/75

Please advise on how to resolve this issue or if there are any updates, patches, or recommendations for a fix. Thank you!

I've sent a fix to this repo from mine but i think this repo is not maintained. You can use my fork of this repository as a workaround.

https://github.com/raister21/flutter_html_to_pdf

jamalbtl commented 10 months ago

@raister21 Thanks buddy, you save my life. I have just added the following in html file and it works. .

<style>
    @media print {
    * {
        -webkit-print-color-adjust: exact !important;
      }
    }
</style>