flutter实践pdf的简单介绍

Flutter——pdf阅读功能的实现

实现pdf阅读、横竖屏切换,以及pdf页面的点击放大和双指放大等功能

成都创新互联专业IDC数据服务器托管提供商,专业提供成都服务器托管,服务器租用,成都服务器托管成都服务器托管,成都多线服务器托管等服务器托管服务。

在这个项目中使用的是 flutter_plugin_pdf_viewer: ^1.0.7 ,可以满足我们最基本的pdf需求阅读需求。所做的满足项目需求的工作主要是横竖屏切换功能,以及我们的初始化继续阅读等等。

首先导入插件部分源码

插件所提供的示例,已经满足了最基本的图片放大、横屏阅读的功能,我们工作的难点就在于pdf竖屏阅读的实现,所以我们需要解决的问题主要有以下几点:

(1) 横屏加载同一页面不能重复流量加载

(2) 切换竖屏时加载速度不能过慢,页面不能有断层

(3) 横竖屏切换时页码的定位保持

针对于上述问题,我们一一进行解决。

重复流量加载 ,解决这一问题比较简单,我们可以利用缓存实现,在每一次加载pdf页时,存储其(key,value),这样在下一次加载时我们会判断这个页面在缓存中是否已经存在,不存在重新加载,存在则调用缓存中的数据,页面销毁时清除所有缓存即可。

切换横竖屏 ,竖屏PDF阅读的实现,思路就是将所有横屏页面存在list中,使用LIstView.builder()进行绘制,这种方法存在的缺点就是太慢了,需要将所有页面全部加载之后,才可以绘制页面,用户体验非常差,所以我们需要做一些改进,为了提升加载速度,实现效果GIF中的效果,我们就要使用FutureBuilder()方法,来实现预加载功能,具体实现如下:

(在这里不对此组件过多介绍,后续会专门介绍此组件的使用),这样我们就可以实现预加载的功能了。

横竖屏切换定位 ,这个点的解决思路已经在我的 (Flutter 初始化ListView定位子组件位置) 中进行了介绍,实现了解决。

至此,我们就解决了所有的难点问题。

Flutter Boost 接入实践(iOS 篇)

本文将简单梳理一下 iOS 工程接入的 Flutter Boost 的流程,以作为前文的补充。

flutter_application_path = '../flutter_module'

load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'FlutterHybridiOS' do

install_all_flutter_pods(flutter_application_path)

end

接着在工程根目录下运行 pod install ,即可集成上 Flutter Module。看到我们的 Pods 中多了以下几个模块,即说明集成成功。

接着在工程根目录下运行 pod install ,即可集成上 Flutter Module。看到我们的 Pods 中多了以下几个模块,即说明集成成功。

这一块直接参照 Flutter Boost 官方提供的 example 就好了:

PlatformRouterImp.h:

PlatformRouterImp.m:

可以看到,Flutter Boost 支持常规 push,也支持打开模态弹窗,也支持手动 pop。

AppDelegate.h:

AppDelegate.m:

同样的,这里可在 Native 端用两种不同的方式去打开我们在 Flutter Module 中注册好的路由名。

至此,我们成功在 iOS 工程中接入了 Flutter Boost,那就开启我们的混编之旅吧~

Flutter实践--屏幕适配

做移动端开发的小伙伴都知道,针对不同型号和尺寸的手机要进行页面适配,且Android和iOS适配方案各不相同,那flutter端如何进行适配呢?以下为近期flutter开发过程中关于适配的一些学习和记录~~~~

说到flutter屏幕适配,就不得不提到插件 flutter_screenutil ,提到flutter_screenutil就不得不说以下几点????

默认宽1080px

默认高1920px

allowFontScaling为false,即不跟随系统字体大小设置变化

初始化单位为px

需要把context传进去,因为内部是通过 MediaQuery 来获取屏幕尺寸等相关信息的

无需再传context,因为内部是通过单例 window 来获取屏幕尺寸等相关信息的

作为iOS开发,之前都是以pt为参照进行比例适配的,且架构组已经定义了一套适配相关常量,传px进去不太方便,所以需要对flutter_screenutil进行扩展

公司设计图是以iPhone X的尺寸提供的即物理设备尺寸为375x812,像素比例为750x1624,像素密度比为2

初始化仍用px来初始化

dart sdk 2.7正式支持 extension-method ,即为已有类扩展方法,从 flutter_screenutil 这种 540.w 写法点进去,我们可以看到

flutter_screenutil为num类扩展了一系列简写方法,那我们当然可以按照它这种方式进行扩展

网上提供的解决方案:

第一步:修改 pubspec.yaml

第二步:执行 flutter pub get

第三步:重启 AndroidStudio

解决方案:去掉const即可

UI设计中px、pt、ppi、dpi、dp、sp之间的关系

Dart/Flutter - 扩展方法(ExtensionMethod)

PDF文件生成

PDF(Portable Document Format)是Adobe公司发明的一种文档格式,由于其具有很多独特的优点而被广泛使用。如pdf可内嵌字体,这样就可以避免客户端没有安装字体而显示不一致;如pdf的图片和文字使用了矢量图,这样就可以随意放大而不会失真;另外pdf的加密和防篡改也是一大亮点,是向外发布资料的首选格式

一个未经修改的PDF文件从头到尾主要包括4个部分,分别是:文件头、对象集合、交叉引用表、文件尾。其中:

%PDF-1.4

1 0 obj

/Producer (Skia/PDF m92)

endobj

xref

0 83

0000000000 65535 f

0000000015 00000 n

0000010954 00000 n

trailer

/Size 83

/Root 11 0 R

/Info 1 0 R

startxref

50152

%%EOF

iOS可以通过UIGraphicsPDFRenderer类生成PDF,其本身的api非常简单:一个init方法,一个写入文件的方法,一个导出data数据的方法

用于构造UIGraphicsPDFRenderer,第一个参数是pdf的尺寸,第二个参数可以设置pdf文件的元数据

生成pdf并写入到指定URL

生成pdf并返回Data

绘制PDF主要依靠 UIGraphicsPDFRendererContext ,这是UIGraphicsRendererContext的子类,所以iOS是使用CoreGraphics的draw api进行pdf绘制的

除了CoreGraphics的相关api之外,最重要的是 func beginPage() ,用于创建一页pdf

安卓可以使用 PdfDocument 类生成PDF,和iOS类似,采用了系统的绘图api( Canvas ),对于开发者来说学习成本很低。但是安卓的坑比较多,建议采用iText、PDFBox等第三方实现。如drawText不支持多行文本,要通过较复杂的操作来实现;某些系统对文档内的图片不进行压缩,导致生成的pdf比正常的大10多倍

flutter可以使用 pdf库 生成pdf,该库实现了一套自己的widgets,开发者可以像写普通widgets一样去写pdf;另外还提供了table相关的api,不用手动画表格,还支持自动分页,非常友好。

Flutter PDF阅读,可显示页数,源码

添加flutter_pdfview: ^1.2.1 组件

class PDFScreenextends StatefulWidget {

final Stringurl;

final Stringpath;

final Stringtitle;

PDFScreen({Key key,this.url, this.path, this.title}) :super(key: key);

_PDFScreenStatecreateState() =_PDFScreenState();

}

class _PDFScreenStateextends Statewith WidgetsBindingObserver {

final Completer_controller =

Completer();

intpages =0;

intcurrentPage =0;

boolisReady =false;

StringerrorMessage ='';

@override

Widgetbuild(BuildContext context) {

return Scaffold(

appBar:AppBar(

elevation:0,

    leading:new IconButton(

icon:Image.asset(

Utils.getImgPath('icon_back'),

        width:18,

        height:36,

      ),

      onPressed: () {

Navigator.of(context).pop();

      },

    ),

    centerTitle:true,

    title:Text(

widget.title,

      style:TextStyle(fontSize:17.0),

    ),

  ),

  body:Stack(

children: [

Positioned(

height: MediaQuery.of(context).size.height - (Utils.getHeightSize(80, context) *2),

          width: MediaQuery.of(context).size.width,

          child:PDFView(

filePath:widget.path,

            enableSwipe:true,

            swipeHorizontal:true,

            autoSpacing:false,

            pageFling:true,

            pageSnap:true,

            defaultPage:currentPage,

            fitPolicy: FitPolicy.BOTH,

            preventLinkNavigation:

false, // if set to true the link is handled in flutter

            onRender: (_pages) {

setState(() {

pages = _pages;

                isReady =true;

              });

            },

            onError: (error) {

setState(() {

errorMessage = error.toString();

              });

              print(error.toString());

            },

            onPageError: (page, error) {

setState(() {

errorMessage ='$page: ${error.toString()}';

              });

              print('$page: ${error.toString()}');

            },

            onViewCreated: (PDFViewController pdfViewController) {

_controller.complete(pdfViewController);

            },

            onLinkHandler: (String uri) {

print('goto uri: $uri');

            },

            onPageChanged: (int page, int total) {

print('page change: $page/$total');

              setState(() {

currentPage = page;

              });

            },

          ),

      ),

      Positioned(

bottom:0,

          height: Utils.getHeightSize(80, context),

          width: MediaQuery.of(context).size.width,

          child:Container(

// padding: EdgeInsets.only(left: 10.0, right: 10.0,top: 10.0,bottom: 10.0),

            decoration:BoxDecoration(

color: Colors.white,

              border:Border.all(color: AppColors.shadeGary),

              boxShadow: [

//refer to :

                BoxShadow(

color: AppColors.shadeGary,

                    offset:Offset(0.0, 0.0),

                    blurRadius:3.0,

                    spreadRadius:0.0),

              ],

            ),

            child:Stack(

children: [

Row(

mainAxisSize: MainAxisSize.min,

                  children: [

Container(),

                    Expanded(child:SizedBox()),

                    Container(

height:42.0,

                      width: Utils.getWidthSize(90, context),

                      margin:EdgeInsets.only(right:20.0,bottom:5.0),

                      decoration:BoxDecoration(//边框线

                        borderRadius:BorderRadius.circular(21.0),  //圆角

                        gradient:LinearGradient(

colors: [Color(0xFF5FD27A), Color(0xFF3FAF6F)],

                        ),

                      ),

                      child:TextButton(

style:ButtonStyle(

overlayColor: MaterialStateProperty.all(Colors.transparent),

                          foregroundColor: MaterialStateProperty.resolveWith(

(states) {

if (states.contains(MaterialState.pressed)) {

//按下时的颜色

                                return Colors.transparent;

                              }

//默认状态使用灰色

                              return Colors.transparent;

                            },

                          ),

                        ),

                        child:Text(

globalTranslations.text("msg_download"),

                          style:TextStyle(color: Colors.white),

                        ),

                        onPressed: () {

launchPdfURL(widget.url);

                        },

                      ),

                    ),

                  ],

                ),

              ],

            ),

          )),

      errorMessage.isEmpty

          ? !isReady

          ?Center(

child:CircularProgressIndicator(),

      )

:Container()

:Center(

child:Text(errorMessage),

      )

],

  ),

  // floatingActionButton: FutureBuilder(

//  future: _controller.future,

//  builder: (context, AsyncSnapshot snapshot) {

//    if (snapshot.hasData) {

//      return FloatingActionButton.extended(

//        label: Text("Go to ${pages ~/ 2}"),

//        onPressed: () async {

//          await snapshot.data.setPage(pages ~/ 2);

//        },

//      );

//    }

//

//    return Container();

//  },

// ),

);

}

launchPdfURL(String url) {

launch(url);

}

}

分享文章:flutter实践pdf的简单介绍
链接分享:https://www.cdcxhl.com/article38/dsihosp.html

成都网站建设公司_创新互联,为您提供营销型网站建设响应式网站面包屑导航服务器托管品牌网站制作软件开发

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

商城网站建设