这是 Kotlin 练习的的第二篇。这一篇的由来是因为刚刚在 Android 开发者官网查看 API 的时候,偶然看到了角落里面的 pdf 相关。 我仔细看看了详细文档,发现这个还蛮有意思的,关键是编码流程很简单。所以就想写篇博客记录备忘一下。本来是用 Java 实现的,后来想到最近自己也在熟悉 Kotlin,于是索性就改成 Kotlin 来实现了。
但是,我一起认为编程最重要的是编程思想,不管 Java 也好, Kotlin 也好,都是为了实现功能的。而本文的主要目的是介绍在 Android 如何创建 PDF 文件。而在实现的过程中,大家可以见识到一些常见的 Kotlin 用法,特别的地方我会稍微讲解一下。比如难于理解的 lambda 表达式我有在代码中运用,然后文中会做比较详细的解释。
用 Kotlin 开发之前,首先得准备语言环境,大家在 Android Studio 安装 Kotlin 的插件,然后重启就好了。这个我不作过多的说明。
接下来就是要引入相关的依赖。我直接张贴我的 build.gradle 文件好了。 顶层 build.gradle
- buildscript {
- ext.support_version ='25.0.1'ext.kotlin_version ='1.1.2'ext.anko_version ='0.8.2'repositories {
- jcenter()
- }
- dependencies {
- classpath'com.android.tools.build:gradle:2.2.0'classpath"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"classpath"org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"// NOTE: Do not place your application dependencies here; they belong
- //inthe individual module build.gradle files
- }
- }
- allprojects {
- repositories {
- jcenter()
- }
- }
- task clean(type: Delete) {
- delete rootProject.buildDir
- }
然后是模块部分的 build.gradle
- apply plugin:'com.android.application'apply plugin:'kotlin-android'apply plugin:'kotlin-android-extensions'android {
- compileSdkVersion25buildToolsVersion"24.0.1"defaultConfig {
- applicationId"com.frank.pdfdemo"minSdkVersion15targetSdkVersion25versionCode1versionName"1.0"testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"}
- buildTypes {
- release {
- minifyEnabledfalseproguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'}
- }
- }
- dependencies {
- compile fileTree(dir:'libs', include: ['*.jar'])
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
- exclude group:'com.android.support', module:'support-annotations'})
- compile"com.android.support:appcompat-v7:$support_version"compile"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"compile"org.jetbrains.anko:anko-common:$anko_version"testCompile'junit:junit:4.12'}
这是最基础的内容,我不说太多,接下来进入主题。
Android SDK 中提供的 PDF 相关类分为两种,它们的作用分别是创建内容和渲染内容。通俗地讲就是一个是用来写 PDF 的,一个是用来展示 PDF 的。
上面的线框图简单明了说明了各个功能相关联的类。我们先从 PDF 文件的创建开始。
需要注意的是,PdfDocument 这个类是在 API 19 的版本中添加的,所以设备必须是 4.4 版本以上。而 PdfRenderer 是在 API 21 的版本中添加的,同样要注意。
先看看官网的文档,上面有介绍基于 SDK 怎么样来创建 PDF 文件的流程。
- //先创建一个 PdfDocument 对象 documentPdfDocument document =newPdfDocument();//创建 PageInfo 对象,用于描述 PDF 中单个的页面PageInfo pageInfo =newPageInfo.Builder(newRect(0,0,100,100),1).create();//开始启动内容填写Page page = document.startPage(pageInfo);//绘制页面,主要是从 page 中获取一个 Canvas 对象。View content = getContentView();
- content.draw(page.getCanvas());//停止对页面的填写document.finishPage(page);
- . . .// 加入更多的 page. . .//将文件写入流document.writeTo(getOutputStream());//关闭流document.close();
示例很详细,接下来我们就可以参考这个流程进行代码的编写。
首先,确定我们要生成一个什么样子的 PDF。因为是做试验用的,所以简单一点,第一页将 MainActivity 的界面截取到 PDF 文件的第 1 页,之后连续写 10 页,每一页画一个圆形,然后绘制一条固定的语句。
我们可以在 MainActivity 的布局文件中随意弄一些布局。
注意布局中的那个按钮,当点击按钮后将生成 PDF 文件, 由于生成 PDF 比较耗时,所以在生成过程中会弹出一个进度对话框,生成成功后将消失,然后打开生成的 PDF 文件。
好了,我们可以创建 Activity 了。
- import kotlinx.android.synthetic.main.activity_main.*
- class MainActivity : AppCompatActivity() {
- private val CODE_WRITE_EXTERNAL =1var file : File? = null
- var mPaint : Paint? = null
- //
- var dialog : ProgressDialog? = null
- var screenWidth : Int =0var screenHeight : Int =0@RequiresApi(Build.VERSION_CODES.KITKAT)
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- btn_test.setOnClickListener{ testCreatPDF(activity_main) }
- mPaint = Paint()
- mPaint.isAntiAlias= true
- mPaint.color= Color.REDscreenWidth = displayMetrics.widthPixelsscreenHeight = displayMetrics.heightPixels}
- @RequiresApi(api = Build.VERSION_CODES.KITKAT)
- private fun creatPDF(view: View) {
- if (dialog == null ) {
- dialog = indeterminateProgressDialog ("正在创建 PDF 中,请稍后...")
- }
- dialog.show()
- async {
- val document = PdfDocument()
- val info = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,1).create()
- val page = document.startPage(info)
- view.draw(page.canvas)
- document.finishPage(page)
- for (indexin 0..10) {
- val info1 = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,index).create()
- val page1 = document.startPage(info1)
- mPaint.color= Color.REDpage1.canvas.drawCircle(100.0f,100.0f,20.0f,mPaint)
- mPaint.color= Color.BLACKmPaint.textSize=36.0f
- page1.canvas.drawText("Kotlin test create PDF page$index.",20.0f,200.0f,mPaint)
- document.finishPage(page1)
- }
- try {
- document.writeTo(outputStream)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- document.close()
- uiThread { toast("生成pdf成功,路径:$file")
- dialog.dismiss()
- }
- // viewPDFByApp()
- viewPDF()
- }
- }
- }
上面的核心方法是
它接收一个 View 对象的参数。在这之前,我得先讲一个小知识点。
- creatPDF(view: View)
大家可以注意到,我在
方法中并没有运用常见的
- onCreate()
但是程序竟然没有报错。其实,我能够这样是因为我 import 了一个包。大家仔细看一下。
- findViewById()
- import kotlinx.android.synthetic.main.activity_main.*
activity_main 正是布局文件。
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/activity_main"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="com.frank.pdfdemo.MainActivity">
- <CheckBox
- android:text="CheckBox"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@+id/radioButton"
- android:layout_toRightOf="@+id/radioButton"
- android:layout_toEndOf="@+id/radioButton"
- android:layout_marginLeft="63dp"
- android:layout_marginStart="63dp"
- android:id="@+id/checkBox"/>
- <Button
- android:id="@+id/btn_test"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="24sp"
- android:text="生成 PDF"
- android:layout_marginLeft="70dp"
- android:layout_marginStart="70dp"
- android:layout_marginBottom="22dp"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"/>
- <RatingBar
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/ratingBar"
- android:layout_above="@+id/btn_test"
- android:layout_alignRight="@+id/btn_test"
- android:layout_alignEnd="@+id/btn_test"/>
- <RadioButton
- android:text="RadioButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/radioButton"
- android:layout_alignParentTop="true"
- android:layout_alignLeft="@+id/ratingBar"
- android:layout_alignStart="@+id/ratingBar"/>
- <EditText
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="textMultiLine"
- android:ems="10"
- android:layout_below="@+id/checkBox"
- android:layout_alignLeft="@+id/radioButton"
- android:layout_alignStart="@+id/radioButton"
- android:layout_marginTop="35dp"
- android:id="@+id/editText"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"/>
- <CalendarView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/calendarView2"
- android:layout_alignLeft="@+id/ratingBar"
- android:layout_alignStart="@+id/ratingBar"
- android:layout_above="@+id/ratingBar"
- android:layout_below="@+id/editText"
- android:layout_alignRight="@+id/checkBox"
- android:layout_alignEnd="@+id/checkBox"/>
- </RelativeLayout>
最外层那个 RelativeLayout 的 id 是 activity_main,所以调用
时这个 view 就是 activity_main,我的目的就是在 PDF 的第一页映射这个布局。聚集到核心方法
- creatPDF(view: View)
上来,我们可以发现一些有趣的东西。
- creatPDF(view: View)
- @RequiresApi(api = Build.VERSION_CODES.KITKAT)
- private fun creatPDF(view: View) {
- async {
- val document = PdfDocument()
- val info = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,1).create()
- val page = document.startPage(info)
- view.draw(page.canvas)
- document.finishPage(page)
- for (indexin 0..10) {
- val info1 = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,index).create()
- val page1 = document.startPage(info1)
- mPaint.color= Color.REDpage1.canvas.drawCircle(100.0f,100.0f,20.0f,mPaint)
- mPaint.color= Color.BLACKmPaint.textSize=36.0f
- page1.canvas.drawText("Kotlin test create PDF page$index.",20.0f,200.0f,mPaint)
- document.finishPage(page1)
- }
- try {
- document.writeTo(outputStream)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- document.close()
- uiThread { toast("生成pdf成功,路径:$file")
- dialog.dismiss()
- }
- // viewPDFByApp()
- viewPDF()
- }
- }
首先,是异步的调用。
- async {......uiThread {......}
- }
之前用 Java 开发 Android 的时候,异步调用通常是用 AsyncTask,但是比较难用。后来大家用 RxJava,感受好多了。现在 Kotlin 方便多了,用一个扩展函数 async 就可以搞定了。 async 其实是 Anko 库中实现的。我们在 build.gradle 引入了它的依赖。
Anko 提供了非常简单的 DSL 来处理异步任务,它满足大部分的需求。它提供了一个基本的 async 函数用于在其它线程执行代码,也可以选择通过调用 uiThread 的方式回到主线程。在子线程中执行请求。就这么简单。
在上面的代码中,我们还可以发现新的大陆:
- btn_test.setOnClickListener {
- testCreatPDF(activity_main)
- }
这是 Kotlin 中 lambda 表达式的具体表现,上面的代码等同于
- btn_test.setOnClickListener(object: View.OnClickListener {overridefun onClick(v: View?) {
- testCreatPDF(activity_main)
- }
- })
上面的形式才是我们在 Java 中常见的形式,用 object 关键字表示匿名内部类,到这一点的时候,大家应该还可以看明白。
但是 Kotlin 神奇的地方在于,它可以对具有函数式接口 (functional Java interface) 进行优化。
函数式接口的定义其实很简单:任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。
值得注意的是这个接口一定是 Java 接口。如果是在 kotlin 中编写这样一个接口却不能这样子,这个地方我被坑了好久。
- public interface Test{
- voidt ( View view);
- }
上面的 Test 就是一个函数式接口, 因为它只有单个方法。在 Kotlin 中可以对这类进行优化,它能够将这类接口直接用一个函数替换。上面的接口优化结果如下:
- // 假设我要创建一个 Test 接口的实现类,我可以这样
- vartest = Test { }
所以
- btn_test.setOnClickListener(object: View.OnClickListener {
- override fun onClick(v: View ? ) {
- testCreatPDF(activity_main)
- }
- }) btn_test.setOnClickListener(View.OnClickListener {
- testCreatPDF(activity_main)
- })
上面两个是等同的。如果一个参数本身没有使用就可以省略。比如这个 v:View 并没有使用。
- btn_test.setOnClickListener({
- testCreatPDF(activity_main)
- })
如果函数最后一个参数是一个 lambda 表达式,则可以将它移动括号外。
- btn_test.setOnClickListener() {
- testCreatPDF(activity_main)
- }
最后,如果括号里面没有参数,也可以省略。
- btn_test.setOnClickListener {
- testCreatPDF(activity_main)
- }
最终可以演变成了这个样子。代码是不是很精简。
现在可以对 lambda 进行一些简单总结 1 一个 lambda 表达式主要用来代替和精简匿名内部类的工作。 2 一个 lambda 表达式被 { } 包围。 3 一个 lambda 表达式通常是 {(T) -> Unit } 形式。箭头左边是参数,参数可选可以省略,右边是函数体。如果参数省略后,箭头也省略。
接下来回归主题,PDF 的制作。
- val document = PdfDocument()
- val info = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,1).create()
- val page = document.startPage(info)
- view.draw(page.canvas)
- document.finishPage(page)
- for (indexin 0..10) {
- val info1 = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,index).create()
- val page1 = document.startPage(info1)
- mPaint.color= Color.REDpage1.canvas.drawCircle(100.0f,100.0f,20.0f,mPaint)
- mPaint.color= Color.BLACKmPaint.textSize=36.0f
- page1.canvas.drawText("Kotlin test create PDF page$index.",20.0f,200.0f,mPaint)
- document.finishPage(page1)
- }
- try {
- document.writeTo(outputStream)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- document.close()
首先,设备下载一个能够读取 PDF 文件的第三方应用。然后编写调用这个应用的代码。当 PDF 文件生成后,申请打开这个文件, 当然本文的后半部就是自己用代码实现 PDF 文件的渲染。调用第三方应用读取 PDF 文件的具体代码如下:
- private fun viewPDFByApp() {
- if (Build.VERSION.SDK_INT >=24) {
- try {
- val m = StrictMode::class.java.getMethod("disableDeathOnFileUriExposure")
- m.invoke(null)
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- var intent = Intent(Intent.ACTION_VIEW)
- intent.flags= Intent.FLAG_ACTIVITY_NEW_TASK
- intent.addCategory(Intent.CATEGORY_DEFAULT)
- intent.setDataAndType(Uri.fromFile(file),"application/pdf")
- startActivity(intent)
- }
我们可以用 Intent.ACTION_VIEW 这个 action,然后设置它的 Uri 和 Type,这里的 Type 是 "application/pdf",大家一看就懂。而由于模拟器是基于 7.0 版本的,直接这样操作会报错。这个 Bug 大家可以参考 stackoverflow 这个页面
好吧。为了防止大家忘记,再次张贴整个代码。
- class MainActivity : AppCompatActivity() {
- private val CODE_WRITE_EXTERNAL =1var file : File? = null
- var mPaint : Paint? = null
- var dialog : ProgressDialog? = null
- var screenWidth : Int =0var screenHeight : Int =0@RequiresApi(Build.VERSION_CODES.KITKAT)
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- btn_test.setOnClickListener{ testCreatPDF(activity_main) }
- mPaint = Paint()
- mPaint.isAntiAlias= true
- mPaint.color= Color.REDscreenWidth = displayMetrics.widthPixelsscreenHeight = displayMetrics.heightPixels}
- @RequiresApi(api = Build.VERSION_CODES.KITKAT)
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults)
- when (requestCode) {
- CODE_WRITE_EXTERNAL ->
- if (grantResults.size>0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- creatPDF(activity_main)
- } else {
- toast("申请权限失败")
- }
- else -> {
- }
- }
- }
- @RequiresApi(api = Build.VERSION_CODES.KITKAT)
- fun testCreatPDF(view: View) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (ContextCompat.checkSelfPermission(this,
- Manifest.permission.READ_EXTERNAL_STORAGE)
- == PackageManager.PERMISSION_GRANTED) {
- creatPDF(view)
- } else {
- requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
- CODE_WRITE_EXTERNAL)
- }
- } else {
- creatPDF(view)
- }
- }
- @RequiresApi(api = Build.VERSION_CODES.KITKAT)
- private fun creatPDF(view: View) {
- if (dialog == null ) {
- dialog = indeterminateProgressDialog ("正在创建 PDF 中,请稍后...")
- }
- dialog.show()
- async {
- val document = PdfDocument()
- val info = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,1).create()
- val page = document.startPage(info)
- view.draw(page.canvas)
- document.finishPage(page)
- for (indexin 0..10) {
- val info1 = PdfDocument.PageInfo.Builder(
- screenWidth,screenHeight,index).create()
- val page1 = document.startPage(info1)
- mPaint.color= Color.REDpage1.canvas.drawCircle(100.0f,100.0f,20.0f,mPaint)
- mPaint.color= Color.BLACKmPaint.textSize=36.0f
- page1.canvas.drawText("Kotlin test create PDF page$index.",20.0f,200.0f,mPaint)
- document.finishPage(page1)
- }
- try {
- document.writeTo(outputStream)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- document.close()
- uiThread { toast("生成pdf成功,路径:$file")
- dialog.dismiss()
- }
- viewPDFByApp()
- }
- }
- private fun viewPDFByApp() {
- if (Build.VERSION.SDK_INT >=24) {
- try {
- val m = StrictMode::class.java.getMethod("disableDeathOnFileUriExposure")
- m.invoke(null)
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- var intent = Intent(Intent.ACTION_VIEW)
- intent.flags= Intent.FLAG_ACTIVITY_NEW_TASK
- intent.addCategory(Intent.CATEGORY_DEFAULT)
- intent.setDataAndType(Uri.fromFile(file),"application/pdf")
- startActivity(intent)
- }
- private val outputStream: OutputStream?
- get() {
- val root = Environment.getExternalStorageDirectory()
- file = File(root,"test.pdf")
- try {
- val os = FileOutputStream(file)
- return os
- } catch (e: FileNotFoundException) {
- e.printStackTrace()
- }
- return null
- }
- }
如果是在 6.0 以上系统,大家还要处理一下权限。可以看到最终生成的 PDF 文档会被保存为 SD 卡上的 test.pdf。至于有些人可能好奇的是 outputStream 变量,我把它形成一个 property 属性,然后复写了它的 get 方法,当它第一次调用时,get() 中的方法体就会执行,然后把结果缓存下来,第二次调用时就直接调用缓存了。
好的,下面我们来实际演练一下。
可以观察到的是,PDF 文件确实是创建了,并且也将 MainActivity 中的布局映射到了第 1 页。并且总共生成了 12 页。
上面例子中,PDF 文件的读取是依靠第三方应用实现的,现在我们要自己实现它。
文章开头的地方,已经说明了这一部分由 PdfRenderer 类来实现。官网上也有它的实现流程。
- // create a new rendererPdfRenderer renderer =newPdfRenderer(getSeekableFileDescriptor());final intpageCount = renderer.getPageCount();for(inti =0; i < pageCount; i++) {
- Page page = renderer.openPage(i);// say we render for showing on the screenpage.render(mBitmap,null,null, Page.RENDER_MODE_FOR_DISPLAY);// do stuff with the bitmap
- // close the pagepage.close();
- }// close the rendererrenderer.close();
相信大家一看就懂。主要核心思想就是通过 PdfRenderer 将每个 Page 的内容渲染在一个 Bitmap 上,有了这个 Bitmap 那么我们肯定能够在 Android 设备上显示了。我们新建一个 Activity 专门用来渲染。 activity_render.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/activity_render"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="com.frank.pdfdemo.RenderActivity">
- <ImageView
- android:id="@+id/iv_render"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- <Button
- android:id="@+id/btn_prev"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:text="上一页"/>
- <Button
- android:id="@+id/btn_next"
- android:layout_toRightOf="@id/btn_prev"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:text="下一页"/>
- </RelativeLayout>
我们用一个 ImageView 来显示渲染出来的 bitmap。然后两个按钮分别来控制上一页和下一页。
然后,我们编写 Activity 的代码。
- import kotlinx.android.synthetic.main.activity_render.*
- class RenderActivity : AppCompatActivity() {
- val TAG : String ="RenderActivity"var renderer : PdfRenderer? = null
- var file : File? = null
- var parcelfd : ParcelFileDescriptor? = null
- var mBitmap : Bitmap? = null
- var mPageCount : Int =0var mCurrentPage : Int =0@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_render)
- file = File(intent.getStringExtra("path"))
- parcelfd = ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_ONLY)
- btn_prev.setOnClickListener{ renderPrev() }
- btn_next.setOnClickListener{ renderNext() }
- mBitmap = Bitmap.createBitmap(displayMetrics.widthPixels,displayMetrics.heightPixels,Bitmap.Config.ARGB_8888)
- startRender()
- show()
- }
- fun show() {
- if (mBitmap != null ) {
- iv_render.setImageBitmap(mBitmap)
- } else {
- Log.d(TAG,"no bitmap")
- }
- }
- @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
- private fun startRender() {
- renderer = PdfRenderer(parcelfd)
- mPageCount = renderer.pageCount!!
- renderPage()
- }
- @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
- override fun onDestroy() {
- super.onDestroy()
- renderer.close()
- }
- @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
- private fun renderPrev() {
- if (mCurrentPage >0) mCurrentPage--
- renderPage()
- Log.d(TAG,"cp:$mCurrentPage,pcount:$mPageCount")
- }
- @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
- private fun renderNext() {
- if (mCurrentPage < mPageCount -1) mCurrentPage++
- renderPage()
- Log.d(TAG,"cp:$mCurrentPage,pcount:$mPageCount")
- }
- @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
- private fun renderPage() {
- async {
- val page = renderer.openPage(mCurrentPage)
- mBitmap = Bitmap.createBitmap(displayMetrics.widthPixels,displayMetrics.heightPixels,Bitmap.Config.ARGB_8888)
- page.render(mBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
- page.close()
- uiThread { show() }
- }
- }
- }
我们在
方法
- onCreate()
来源: http://blog.csdn.net/briblue/article/details/72779147