Linux 桌面版 Flutter PDF 查看器

Flutter PDF Viewer for Linux desktop

我在 Flutter 上为 Android 和 Linux 桌面平台开发了某种具有 PDF 查看功能的聊天应用程序。

所以我想使用某种 PDF reader 或 WebBrowser 将 PDF 查看器嵌入到 flutter 应用程序中。 Android 上的 PDF 没有问题 - pub.dev 上有 100 多个用于 PDF 和 WebView 的插件,但其中 none 支持 Linux 桌面.

我尝试为 Android 和 IOS 插件添加 Linux 桌面支持,但看起来它们都使用 PlatformView 和 webview_flutter 类 ,Linux 桌面尚不支持:webview_flutter PlatformView。他们具有 P4 优先级并且没有分配里程碑。我不能无限期地等待,我应该在 2 个月内结束这个项目。那我该怎么办呢?

我读到 Flutter 使用 GTK+ 在 Linux 桌面上显示,我知道有 GTK+ components to display PDF。那么是否有可能以某种方式在 flutter ui 中注入这个组件?有例子吗?

或者更好的方法是将 PDF 转换为 jpeg 格式并改为显示图像? (但我不想丢失缩放和文档导航)

用 File.Open() 打开 PDF 到外部程序对我来说不是解决方案,因为在这种情况下,用户应该不断地在 flutter 应用程序(我们有 PDF 文件列表)和 PDF reader windows.

我是 Flutter 和 Linux 的新手,所以任何帮助将不胜感激。

So is it possible to inject somehow this component in flutter ui?

这正是 PlatformView 的意思,所以这相当于 Linux 是否支持 PlatformView 的问题。

在没有 PlatformView 支持的情况下可以使用的两个选项:

  • 在显示 Flutter 视图和 PDF 视图之间交换 window(如果您希望 PDF 在显示时填充 window)。
  • 将 Flutter 视图和 PDF 视图并排放置在 window 中(如果您希望同时显示 Flutter 内容(如文件列表)和 PDF 内容)。

两者都需要在本机代码中完成工作,因此您需要编写一个插件,或者直接在您的运行器中实现它,并使用方法通道在 Dart 和本机代码之间进行协调。

所以只是为了阐明我们如何使用 webkit 实现这一点,例如:

CMakeLists.txt:

#add webkit package reference
pkg_check_modules(WEBKIT2 REQUIRED IMPORTED_TARGET webkit2gtk-4.0)
...
#remove -Werror flag to allow compilation with warnings
target_compile_options(${TARGET} PRIVATE -Wall)
...
#link webkit libraries
target_link_libraries(${BINARY_NAME} PUBLIC PkgConfig::WEBKIT2) 
#somehow this line causes 'flutter run' to crash on "Linking CXX executable" step.
#Looks like it compiles, but fails to link. 
#I think there is should be other question opened for this issue. 

my_application.cc:

#include "my_application.h"
#include <flutter_linux/flutter_linux.h>
#include <webkit2/webkit2.h>
#include "flutter/generated_plugin_registrant.h"

static void my_application_activate(GApplication* application) {

  GtkWidget *vbox1 = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox1);

  // we can insert any gtk controls in this window outside of FlView
  GtkWidget *label = gtk_label_new ("Hello GNOME!");
  gtk_box_pack_start (GTK_BOX (vbox1), label, TRUE, TRUE, 2);
  gtk_widget_show (label);

  // webkit/poppler/evince should work perfect because they gtk+
  WebKitWebView *pWebKitView = WEBKIT_WEB_VIEW(webkit_web_view_new());
  gtk_box_pack_start (GTK_BOX (vbox1), GTK_WIDGET(pWebKitView), TRUE, TRUE, 2);
  gtk_widget_show(GTK_WIDGET(pWebKitView));

  // finally add FlView
  g_autoptr(FlDartProject) project = fl_dart_project_new();
  FlView *view = fl_view_new(project);
  gtk_box_pack_start (GTK_BOX (vbox1), GTK_WIDGET(view), TRUE, TRUE, 2);
  gtk_widget_show (GTK_WIDGET (view));

  GtkWindow* window =
  GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
  gtk_container_add (GTK_CONTAINER (window), vbox1);

  fl_register_plugins(FL_PLUGIN_REGISTRY(view));
  gtk_widget_grab_focus(GTK_WIDGET(view));

  GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
  gtk_widget_show(GTK_WIDGET(header_bar));
  gtk_header_bar_set_title(header_bar, "client");
  gtk_header_bar_set_show_close_button(header_bar, TRUE);
  gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
  gtk_window_set_default_size(window, 1280, 720);

  gtk_widget_show(GTK_WIDGET(window));
}