这是 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
// in the 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 {
compileSdkVersion 25
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.frank.pdfdemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles 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 PDF 相关 API
Android SDK 中提供的 PDF 相关类分为两种,它们的作用分别是创建内容和渲染内容。通俗地讲就是一个是用来写 PDF 的,一个是用来展示 PDF 的。
上面的线框图简单明了说明了各个功能相关联的类。我们先从 PDF 文件的创建开始。
需要注意的是,PdfDocument 这个类是在 API 19 的版本中添加的,所以设备必须是 4.4 版本以上。而 PdfRenderer 是在 API 21 的版本中添加的,同样要注意。
创建 PDF 文件
先看看官网的文档,上面有介绍基于 SDK 怎么样来创建 PDF 文件的流程。
//先创建一个 PdfDocument 对象 document
PdfDocument document = new PdfDocument();
//创建 PageInfo 对象,用于描述 PDF 中单个的页面
PageInfo pageInfo = new PageInfo.Builder(new Rect(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 = 1
var file : File? = null
var mPaint : Paint? = null
//
var dialog : ProgressDialog? = null
var screenWidth : Int = 0
var 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.RED
screenWidth = displayMetrics.widthPixels
screenHeight = 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 (index in 0..10) {
val info1 = PdfDocument.PageInfo.Builder(
screenWidth,screenHeight,index).create()
val page1 = document.startPage(info1)
mPaint?.color = Color.RED
page1.canvas.drawCircle(100.0f,100.0f,20.0f,mPaint)
mPaint?.color = Color.BLACK
mPaint?.textSize = 36.0f
page1.canvas.drawText("Kotlin test create PDF page$index.",
20.0f,200.0f,mPaint)
document