Commit c30c7593 authored by wanglei's avatar wanglei

...

parent ec932d27
...@@ -15,6 +15,16 @@ android { ...@@ -15,6 +15,16 @@ android {
versionName = "1.0" versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// ndk {
// abiFilters.add("arm64-v8a")
// // 取消注释以下行以添加更多 ABI 支持
// abiFilters.add("armeabi-v7a")
// }
// sourceSets {
// getByName("main") {
// jniLibs.srcDirs("src/main/jniLibs")
// }
// }
} }
buildTypes { buildTypes {
...@@ -34,13 +44,8 @@ android { ...@@ -34,13 +44,8 @@ android {
viewBinding = true viewBinding = true
buildConfig = true buildConfig = true
} }
sourceSets {
getByName("main") {
assets {
srcDirs("src\\main\\assets", "src\\main\\assets")
}
}
}
} }
dependencies { dependencies {
......
package com.base.pdfviewerscannerwhite.ui.document.pdf package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.util.DisplayMetrics
import android.view.View import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import androidx.activity.addCallback
import androidx.core.widget.addTextChangedListener
import com.artifex.mupdfdemo.Annotation
import com.artifex.mupdfdemo.Hit
import com.artifex.mupdfdemo.MuPDFCore import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.MuPDFPageAdapter
import com.artifex.mupdfdemo.MuPDFReaderView
import com.artifex.mupdfdemo.MuPDFReaderViewListener
import com.artifex.mupdfdemo.MuPDFView
import com.artifex.mupdfdemo.SearchTask
import com.artifex.mupdfdemo.SearchTaskResult import com.artifex.mupdfdemo.SearchTaskResult
import com.base.pdfviewerscannerwhite.bean.PdfPageBean import com.base.pdfviewerscannerwhite.bean.PdfPageBean
import com.base.pdfviewerscannerwhite.databinding.ActivityPdfBinding import com.base.pdfviewerscannerwhite.databinding.ActivityPdfBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfLoadingActivity.Companion.DO_SAVE_PDF
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import java.io.File import java.io.File
...@@ -14,10 +34,15 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView { ...@@ -14,10 +34,15 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
private lateinit var pdfPresenter: PdfPresenter private lateinit var pdfPresenter: PdfPresenter
private lateinit var pdfPageAdapter: PdfPagerAdapter
private var muPDFCore: MuPDFCore? = null // 加载mupdf.so文件 private var muPDFCore: MuPDFCore? = null // 加载mupdf.so文件
private var searchTask: SearchTask? = null
private var uiMode = UI_MODE_NORMAL private var uiMode = UI_MODE_NORMAL
private var saveMode = ""
private var path: String = "" private var path: String = ""
private var density = 0f
override val binding: ActivityPdfBinding by lazy { override val binding: ActivityPdfBinding by lazy {
ActivityPdfBinding.inflate(layoutInflater) ActivityPdfBinding.inflate(layoutInflater)
...@@ -26,29 +51,323 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView { ...@@ -26,29 +51,323 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
override fun initView() { override fun initView() {
val metrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(metrics)
density = metrics.density
path = intent.extras?.getString("path") ?: "" path = intent.extras?.getString("path") ?: ""
val file = File(path) val file = File(path)
binding.tvPdfName.text = file.name binding.tvPdfName.text = file.name
pdfPresenter = PdfPresenter(this, this) pdfPresenter = PdfPresenter(this, this)
initAdapter()
changeNormalUI()
muPDFCore = pdfPresenter.openFile(path) muPDFCore = pdfPresenter.openFile(path)
// 搜索设为空 // 搜索设为空
SearchTaskResult.set(null) SearchTaskResult.set(null)
if (muPDFCore == null) { if (muPDFCore == null) {
toast("can't open pdf") toast("can't open pdf")
} } else {
pdfPresenter.iniPdfPage(path)
createPdfUI() createPdfUI()
}
}
override fun initListener() {
onBackPressedDispatcher.addCallback {
if (uiMode == UI_MODE_SEARCH) {
changeNormalUI()
return@addCallback
}
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.llHighlight.setOnClickListener {
saveMode = SAVE_MODE_HIGHLIGHT
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
}
binding.llGlideLine.setOnClickListener {
saveMode = SAVE_MODE_GLIDE_LINE
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
}
binding.llStrikethrough.setOnClickListener {
saveMode = SAVE_MODE_STRIKETHROUGH
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
}
binding.llPaintingBrush.setOnClickListener {
saveMode = SAVE_MODE_PAINTING_BRUSH
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Drawing)
}
binding.ivWancheng.setOnClickListener {
var success: Boolean = false
val pageView = binding.mupdfReaderView.displayedView as MuPDFView
when (saveMode) {
SAVE_MODE_HIGHLIGHT -> {
success = pageView.markupSelection(Annotation.Type.HIGHLIGHT)
}
SAVE_MODE_GLIDE_LINE -> {
success = pageView.markupSelection(Annotation.Type.UNDERLINE)
}
SAVE_MODE_STRIKETHROUGH -> {
success = pageView.markupSelection(Annotation.Type.STRIKEOUT)
}
SAVE_MODE_PAINTING_BRUSH -> {
success = pageView.saveDraw()
}
}
if (!success) {
toast("nothing to save")
return@setOnClickListener
}
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
changeEditSaveUI()
}
binding.ivBianji.setOnClickListener {
bianJiScaleXiao {
changeEditSaveUI()
}
}
binding.ivSearch.setOnClickListener {
bianJiScaleXiao {
changeSearchUI()
binding.editSearch.requestFocus()
}
}
binding.editSearch.addTextChangedListener {
if (SearchTaskResult.get() != null && it.toString() != SearchTaskResult.get().txt) {
SearchTaskResult.set(null as SearchTaskResult?)
binding.mupdfReaderView.resetupChildren()
}
}
binding.editSearch.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
search(1)
}
false
}
binding.tvBtnSave.setOnClickListener {
PdfLoadingActivity.muPDFCore = muPDFCore
changeNormalUI()
startActivity(Intent(this, PdfLoadingActivity::class.java).apply {
putExtra("doWhat", DO_SAVE_PDF)
})
}
}
/**
* 有个问题,一旦pdf某页编辑后加个蒙层,搜索功能就是失效了
*/
private fun search(direction: Int) {
this.hideKeyboard()
val displayPage: Int = binding.mupdfReaderView.displayedViewIndex
val r = SearchTaskResult.get()
val searchPage = r?.pageNumber ?: -1
searchTask?.go(binding.editSearch.text.toString(), direction, displayPage, searchPage)
}
private fun initAdapter() {
pdfPageAdapter = PdfPagerAdapter(path)
pdfPageAdapter.clickAction = { pageIndex ->
binding.mupdfReaderView.displayedViewIndex = pageIndex
}
binding.rvPager.adapter = pdfPageAdapter
}
@SuppressLint("ServiceCast")
private fun hideKeyboard() {
val imm = this.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.editSearch.windowToken, 0)
}
private var isShowTopBottomLayout = true
private fun hideTopBottomLayout() {
if (isShowTopBottomLayout) {
isShowTopBottomLayout = false
hideKeyboard()
val topAnim: Animation = TranslateAnimation(0f, 0f, 0f, -binding.vAnimatorTop.height.toFloat())
topAnim.setDuration(200)
topAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
binding.vAnimatorTop.visibility = View.GONE
}
})
binding.vAnimatorTop.startAnimation(topAnim)
val bottomAnim: Animation = TranslateAnimation(0f, 0f, 0f, binding.vAnimatorBottom.height.toFloat())
bottomAnim.duration = 200
bottomAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
binding.vAnimatorBottom.visibility = View.GONE
}
})
binding.vAnimatorBottom.startAnimation(bottomAnim)
bianJiScaleXiao()
}
}
private fun showTopBottomLayout() {
if (!isShowTopBottomLayout) {
isShowTopBottomLayout = true
val topAnim: Animation = TranslateAnimation(0f, 0f, -binding.vAnimatorTop.height.toFloat(), 0f)
topAnim.setDuration(200)
topAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
binding.vAnimatorTop.visibility = View.VISIBLE
}
changeEditSelectUI(binding.llHighlight) override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
}
})
binding.vAnimatorTop.startAnimation(topAnim)
val bottomAnim: Animation = TranslateAnimation(0f, 0f, binding.vAnimatorBottom.height.toFloat(), 0f)
bottomAnim.duration = 200
bottomAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
binding.vAnimatorBottom.visibility = View.VISIBLE
}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
}
})
binding.vAnimatorBottom.startAnimation(bottomAnim)
bianJiScaleDa()
}
}
private fun bianJiScaleDa() {
val scaleXAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleX", 0f, 1.0f)
scaleXAnimator.duration = 200
val scaleYAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleY", 0f, 1.0f)
scaleYAnimator.duration = 200
val animatorSet = AnimatorSet()
animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
animatorSet.start()
}
private fun bianJiScaleXiao(endAction: (() -> Unit)? = null) {
val scaleXAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleX", 1.0f, 0f)
scaleXAnimator.duration = 200
val scaleYAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleY", 1.0f, 0f)
scaleYAnimator.duration = 200
val animatorSet = AnimatorSet()
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) = Unit
override fun onAnimationEnd(animation: Animator) {
endAction?.invoke()
}
override fun onAnimationCancel(animation: Animator) = Unit
override fun onAnimationRepeat(animation: Animator) = Unit
})
animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
animatorSet.start()
} }
/** /**
* 构建pdf的ui * 构建pdf的ui
*/ */
@SuppressLint("SetTextI18n")
private fun createPdfUI() { private fun createPdfUI() {
if (muPDFCore == null) return if (muPDFCore == null) return
binding.tvPageCount.text = "1/${muPDFCore?.countPages()}"
binding.mupdfReaderView.setListener(object : MuPDFReaderViewListener {
@SuppressLint("SetTextI18n")
override fun onMoveToChild(i: Int) {
binding.tvPageCount.text = "${i + 1}/${muPDFCore?.countPages()}"
pdfPageAdapter.changeSelectPager(i)
}
override fun onTapMainDocArea() {
if (isShowTopBottomLayout) {
hideTopBottomLayout()
} else {
showTopBottomLayout()
}
}
override fun onDocMotion() {
}
override fun onHit(item: Hit?) {
}
})
binding.mupdfReaderView.adapter = MuPDFPageAdapter(this, {}, muPDFCore)
binding.mupdfReaderView.setBackgroundColor(Color.parseColor("#E0D5FA"))
binding.mupdfReaderView.setHorizontalScrolling(false)
searchTask = object : SearchTask(this, muPDFCore) {
override fun onTextFound(result: SearchTaskResult?) {
SearchTaskResult.set(result)
binding.mupdfReaderView.displayedViewIndex = result?.pageNumber ?: 0
binding.mupdfReaderView.resetupChildren()
}
}
}
/**
* 普通模式
*/
private fun changeNormalUI() {
uiMode = UI_MODE_NORMAL
binding.clOperation.visibility = View.GONE
binding.tvBtnSave.visibility = View.GONE
binding.ivXuanzhuan.visibility = View.VISIBLE
binding.ivSearch.visibility = View.VISIBLE
binding.ivMore.visibility = View.VISIBLE
binding.rvPager.visibility = View.VISIBLE
}
/**
* 搜索模式UI
*/
private fun changeSearchUI() {
uiMode = UI_MODE_SEARCH
binding.ivXuanzhuan.visibility = View.INVISIBLE
binding.ivMore.visibility = View.GONE
binding.tvPdfName.visibility = View.INVISIBLE
binding.rvPager.visibility = View.GONE
binding.clOperation.visibility = View.GONE
binding.editSearch.visibility = View.VISIBLE
} }
...@@ -56,7 +375,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView { ...@@ -56,7 +375,7 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
/** /**
* 编辑选择UI模式 * 编辑选择UI模式
*/ */
fun changeEditSelectUI(view: View) { private fun changeEditSelectUI(view: View) {
uiMode = UI_MODE_EDITE_SELECT uiMode = UI_MODE_EDITE_SELECT
binding.tvBtnSave.visibility = View.GONE binding.tvBtnSave.visibility = View.GONE
...@@ -65,7 +384,6 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView { ...@@ -65,7 +384,6 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
binding.ivSearch.visibility = View.INVISIBLE binding.ivSearch.visibility = View.INVISIBLE
binding.ivMore.visibility = View.INVISIBLE binding.ivMore.visibility = View.INVISIBLE
binding.clOperation.visibility = View.VISIBLE
binding.ivWancheng.visibility = View.VISIBLE binding.ivWancheng.visibility = View.VISIBLE
if (binding.llHighlight == view) { if (binding.llHighlight == view) {
...@@ -90,17 +408,47 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView { ...@@ -90,17 +408,47 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
} }
} }
/**
* 编辑报错UI模式
*/
private fun changeEditSaveUI() {
binding.ivWancheng.visibility = View.INVISIBLE
binding.ivMore.visibility = View.INVISIBLE
binding.ivXuanzhuan.visibility = View.INVISIBLE
binding.ivSearch.visibility = View.INVISIBLE
binding.clOperation.visibility = View.VISIBLE
binding.tvBtnSave.visibility = View.VISIBLE
binding.rvPager.visibility = View.VISIBLE
binding.llHighlight.setBackgroundColor(Color.TRANSPARENT)
binding.llGlideLine.setBackgroundColor(Color.TRANSPARENT)
binding.llStrikethrough.setBackgroundColor(Color.TRANSPARENT)
binding.llPaintingBrush.setBackgroundColor(Color.TRANSPARENT)
}
override fun onPause() {
super.onPause()
searchTask?.stop()
}
companion object { companion object {
const val UI_MODE_NORMAL = 0 const val UI_MODE_NORMAL = 0
const val UI_MODE_SEARCH = 1 const val UI_MODE_SEARCH = 1
const val UI_MODE_EDITE_SAVE = 2 const val UI_MODE_EDITE_SAVE = 2
const val UI_MODE_EDITE_SELECT = 3 const val UI_MODE_EDITE_SELECT = 3
const val SAVE_MODE_HIGHLIGHT = "Highlight"
const val SAVE_MODE_GLIDE_LINE = "Glide Line"
const val SAVE_MODE_STRIKETHROUGH = "Strikethrough"
const val SAVE_MODE_PAINTING_BRUSH = "Painting Brush"
} }
override fun initPdfPageRv(items: List<PdfPageBean>) { override fun initPdfPageRv(items: List<PdfPageBean>) {
pdfPageAdapter.submitList(items)
pdfPageAdapter.changeSelectPager(0)
} }
} }
\ No newline at end of file
...@@ -2,21 +2,21 @@ package com.base.pdfviewerscannerwhite.ui.document.pdf ...@@ -2,21 +2,21 @@ package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.content.Intent import android.content.Intent
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.artifex.mupdfdemo.MuPDFCore
import com.base.pdfviewerscannerwhite.databinding.ActivityPdfLoadingBinding import com.base.pdfviewerscannerwhite.databinding.ActivityPdfLoadingBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import kotlin.random.Random
class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() { class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
private val TAG = "PdfLoadingActivity" private val TAG = "PdfLoadingActivity"
private var doWhat = ""
private var srcPath: String = "" private var srcPath: String = ""
private var newName: String = "" private var newPath: String = ""
private var splitIndex: List<Int> = listOf() private var splitIndex: List<Int> = listOf()
private lateinit var pdfPresenter: PdfPresenter private lateinit var pdfPresenter: PdfPresenter
...@@ -24,16 +24,36 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() { ...@@ -24,16 +24,36 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
ActivityPdfLoadingBinding.inflate(layoutInflater) ActivityPdfLoadingBinding.inflate(layoutInflater)
} }
var isFinishBoolean: Boolean = false private var isFinishBoolean: Boolean = false
var newPdfFile: File? = null private var progressFinishAction: (() -> Unit)? = null
override fun initView() { override fun initView() {
pdfPresenter = PdfPresenter(this) pdfPresenter = PdfPresenter(this)
initSpPa() initSpPa()
pdfPresenter.splitPdf(File(srcPath), newName, splitIndex, finishAction = { when (doWhat) {
newPdfFile = it DO_SPLIT_PDF -> {
progressFinishAction = {
finish()
}
pdfPresenter.splitPdf(srcPath, newPath, splitIndex, finishAction = {
isFinishBoolean = true isFinishBoolean = true
}) })
}
DO_SAVE_PDF -> {
muPDFCore?.save()
muPDFCore = null
progressFinishAction = {
finish()
}
lifecycleScope.launch {
delay(Random.nextLong(1500, 2500))
isFinishBoolean = true
}
}
}
startProgress() startProgress()
} }
...@@ -49,18 +69,22 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() { ...@@ -49,18 +69,22 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
} }
delay(500) delay(500)
} }
if (newPdfFile == null) { progressFinishAction?.invoke()
toast("split pdf failed!")
finish()
return@launch
}
} }
private fun initSpPa() { private fun initSpPa() {
doWhat = intent?.extras?.getString("doWhat", "") ?: ""
srcPath = intent?.extras?.getString("srcPath", "") ?: "" srcPath = intent?.extras?.getString("srcPath", "") ?: ""
newName = intent?.extras?.getString("newName", "") ?: "" newPath = intent?.extras?.getString("newPath", "") ?: ""
splitIndex = intent.extras?.getString("splitIndex")?.split(",")?.map { it.toInt() } ?: listOf() splitIndex = intent.extras?.getString("splitIndex")?.split(",")?.map { it.toInt() } ?: listOf()
} }
companion object {
var muPDFCore: MuPDFCore? = null
const val DO_SPLIT_PDF = "do_split_pdf"
const val DO_SAVE_PDF = "do_save_pdf"
}
} }
\ No newline at end of file
...@@ -88,7 +88,6 @@ class PdfPagerAdapter(val pdfPath: String, val itemLayout: Int = R.layout.item_p ...@@ -88,7 +88,6 @@ class PdfPagerAdapter(val pdfPath: String, val itemLayout: Int = R.layout.item_p
runCatching { runCatching {
val drawable = PdfBoxUtils.getPdfDrawablePage(context, pdfPath, item.pageIndex, scale) val drawable = PdfBoxUtils.getPdfDrawablePage(context, pdfPath, item.pageIndex, scale)
item.pageDrawable = drawable item.pageDrawable = drawable
// 任务代码
itemView.post { itemView.post {
item.pageDrawable?.let { item.pageDrawable?.let {
iv.setImageDrawable(it) iv.setImageDrawable(it)
......
package com.base.pdfviewerscannerwhite.ui.document.pdf package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.content.Context import android.content.Context
import android.os.Handler
import android.util.Log
import com.artifex.mupdfdemo.MuPDFCore import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.OutlineActivityData import com.artifex.mupdfdemo.OutlineActivityData
import com.base.pdfviewerscannerwhite.bean.PdfPageBean import com.base.pdfviewerscannerwhite.bean.PdfPageBean
...@@ -15,14 +13,12 @@ class PdfPresenter( ...@@ -15,14 +13,12 @@ class PdfPresenter(
val context: Context, val context: Context,
val pdfView: PdfView? = null val pdfView: PdfView? = null
) { ) {
private val TAG = "PdfPresenter"
var handler: Handler? = null
fun openFile(path: String): MuPDFCore? { fun openFile(path: String): MuPDFCore? {
val muPDFCore: MuPDFCore? = null var muPDFCore: MuPDFCore? = null
try { try {
MuPDFCore(context, path) muPDFCore = MuPDFCore(context, path)
// 新建:删除旧的目录数据 // 新建:删除旧的目录数据
OutlineActivityData.set(null) OutlineActivityData.set(null)
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
...@@ -44,13 +40,13 @@ class PdfPresenter( ...@@ -44,13 +40,13 @@ class PdfPresenter(
} }
fun splitPdf( fun splitPdf(
file: File, newName: String, splitIndex: List<Int>, srcPath: String, newPath: String, splitIndex: List<Int>,
finishAction: (newFile: File?) -> Unit finishAction: (newFile: File?) -> Unit
) = Thread { ) = Thread {
val newFile = File(file.parentFile, newName)
try { try {
// 加载现有 PDF 文档 // 加载现有 PDF 文档
val sourceDocument = PDDocument.load(file) val sourceDocument = PDDocument.load(File(srcPath))
// 创建新的 PDF 文档 // 创建新的 PDF 文档
val newDocument = PDDocument() val newDocument = PDDocument()
...@@ -61,7 +57,7 @@ class PdfPresenter( ...@@ -61,7 +57,7 @@ class PdfPresenter(
newDocument.addPage(page) newDocument.addPage(page)
} }
// 保存新的 PDF 文档 // 保存新的 PDF 文档
newDocument.save(newFile) newDocument.save(newPath)
newDocument.close() newDocument.close()
sourceDocument.close() sourceDocument.close()
} catch (e: Exception) { } catch (e: Exception) {
...@@ -69,6 +65,48 @@ class PdfPresenter( ...@@ -69,6 +65,48 @@ class PdfPresenter(
finishAction.invoke(null) finishAction.invoke(null)
return@Thread return@Thread
} }
finishAction.invoke(newFile) finishAction.invoke(File(newPath))
}.start() }.start()
fun createNewPath(path: String): String {
val file = File(path)
var newName = file.name.split(".")[0]
//aaaa_1.pdf
if (isUnderscoreNumberSuffix(newName)) {
val nameSplit = newName.split("_")
val number = nameSplit[1].toInt() + 1
newName = "${nameSplit[0]}_$number"
} else {
newName = "${newName}_1"
}
val newFile = File(file.parentFile, "$newName.pdf")
if (!newFile.exists()) {
newFile.createNewFile()
}
return newFile.absolutePath
}
private fun isUnderscoreNumberSuffix(input: String): Boolean {
val pattern = "_\\d+$".toRegex()
return pattern.matches(input)
}
fun savePdf(context: Context, muPDFCore: MuPDFCore?, srcPath: String, newPath: String) {
//保存的逻辑,
// 1.原本的文件拷贝一份
// 2。然后保存修改到原本的文件,重名命名该文件为新文件
// 3.拷贝的文件在恢复原位置
val tempFile = File(context.filesDir, "temp.pdf")
if (!tempFile.exists()) {
tempFile.createNewFile()
}
File(srcPath).compareTo(tempFile)
muPDFCore?.save()
val newFile = File(newPath)
}
} }
\ No newline at end of file
...@@ -7,10 +7,11 @@ ...@@ -7,10 +7,11 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".ui.document.pdf.PdfActivity"> tools:context=".ui.document.pdf.PdfActivity">
<!-- <com.artifex.mupdfdemo.MuPDFReaderView--> <com.artifex.mupdfdemo.MuPDFReaderView
<!-- android:id="@+id/mupdf_reader_view"--> android:id="@+id/mupdf_reader_view"
<!-- android:layout_width="match_parent"--> android:layout_width="match_parent"
<!-- android:layout_height="match_parent" />--> android:layout_height="match_parent" />
<ViewAnimator <ViewAnimator
android:id="@+id/v_animator_top" android:id="@+id/v_animator_top"
...@@ -134,7 +135,7 @@ ...@@ -134,7 +135,7 @@
android:textSize="16sp" android:textSize="16sp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/iv_xuanzhuan" app:layout_constraintEnd_toEndOf="@+id/iv_more"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
...@@ -142,10 +143,27 @@ ...@@ -142,10 +143,27 @@
</ViewAnimator> </ViewAnimator>
<TextView
android:id="@+id/tv_pageCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="28dp"
android:background="@drawable/bg_54585b_5"
android:includeFontPadding="false"
android:paddingHorizontal="2dp"
android:paddingVertical="2dp"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_animator_top"
tools:text="1/3" />
<ViewAnimator <ViewAnimator
android:id="@+id/v_animator_bottom" android:id="@+id/v_animator_bottom"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/white" android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"> app:layout_constraintBottom_toBottomOf="parent">
...@@ -160,14 +178,17 @@ ...@@ -160,14 +178,17 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/white" android:background="@color/white"
android:paddingVertical="8dp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/v_animator_bottom"> app:layout_constraintBottom_toTopOf="@id/v_animator_bottom">
<LinearLayout <LinearLayout
android:id="@+id/ll_highlight" android:id="@+id/ll_highlight"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_glide_line" app:layout_constraintEnd_toStartOf="@id/ll_glide_line"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
...@@ -194,8 +215,10 @@ ...@@ -194,8 +215,10 @@
<LinearLayout <LinearLayout
android:id="@+id/ll_glide_line" android:id="@+id/ll_glide_line"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_strikethrough" app:layout_constraintEnd_toStartOf="@id/ll_strikethrough"
app:layout_constraintStart_toEndOf="@id/ll_highlight" app:layout_constraintStart_toEndOf="@id/ll_highlight"
...@@ -222,8 +245,10 @@ ...@@ -222,8 +245,10 @@
<LinearLayout <LinearLayout
android:id="@+id/ll_strikethrough" android:id="@+id/ll_strikethrough"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_painting_brush" app:layout_constraintEnd_toStartOf="@id/ll_painting_brush"
app:layout_constraintStart_toEndOf="@id/ll_glide_line" app:layout_constraintStart_toEndOf="@id/ll_glide_line"
...@@ -252,6 +277,7 @@ ...@@ -252,6 +277,7 @@
android:id="@+id/ll_painting_brush" android:id="@+id/ll_painting_brush"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ll_strikethrough" app:layout_constraintStart_toEndOf="@id/ll_strikethrough"
...@@ -294,4 +320,16 @@ ...@@ -294,4 +320,16 @@
</ViewAnimator> </ViewAnimator>
<ImageView
android:id="@+id/iv_bianji"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="15dp"
android:layout_marginBottom="108dp"
android:src="@mipmap/bianji"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
android:layout_marginHorizontal="56dp" android:layout_marginHorizontal="56dp"
android:layout_marginTop="19dp" android:layout_marginTop="19dp"
android:max="100" android:max="100"
android:progress="50"
android:progressDrawable="@drawable/progress_bg" android:progressDrawable="@drawable/progress_bg"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
......
...@@ -4,11 +4,23 @@ plugins { ...@@ -4,11 +4,23 @@ plugins {
id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.android'
} }
android { android {
compileSdkVersion 28
namespace "com.lonelypluto.pdfviewerlibrary" namespace "com.lonelypluto.pdfviewerlibrary"
compileSdk 34
defaultConfig { defaultConfig {
minSdkVersion 17 minSdk 24
targetSdk 34
ndk {
abiFilters "arm64-v8a"
// "armeabi-v7a"
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
} }
buildTypes { buildTypes {
...@@ -25,6 +37,5 @@ android { ...@@ -25,6 +37,5 @@ android {
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
// implementation 'com.android.support:appcompat-v7:28.0.0'
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
} }
\ No newline at end of file
...@@ -4,7 +4,9 @@ import android.content.Context; ...@@ -4,7 +4,9 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.RectF; import android.graphics.RectF;
import java.util.ArrayList; import java.util.ArrayList;
import com.lonelypluto.pdfviewerlibrary.R; import com.lonelypluto.pdfviewerlibrary.R;
public class MuPDFCore { public class MuPDFCore {
...@@ -12,10 +14,12 @@ public class MuPDFCore { ...@@ -12,10 +14,12 @@ public class MuPDFCore {
private static boolean gs_so_available = false; private static boolean gs_so_available = false;
static { static {
try {
System.out.println("Loading dll"); System.out.println("Loading dll");
System.loadLibrary("mupdf_java"); System.loadLibrary("mupdf_java");
System.out.println("Loaded dll"); System.out.println("Loaded dll");
if (gprfSupportedInternal()) { Boolean flag = gprfSupportedInternal();
if (flag) {
try { try {
System.loadLibrary("gs"); System.loadLibrary("gs");
gs_so_available = true; gs_so_available = true;
...@@ -23,6 +27,10 @@ public class MuPDFCore { ...@@ -23,6 +27,10 @@ public class MuPDFCore {
gs_so_available = false; gs_so_available = false;
} }
} }
} catch (Exception e) {
e.printStackTrace();
}
} }
/* Readable members */ /* Readable members */
......
...@@ -14,9 +14,7 @@ import android.view.View; ...@@ -14,9 +14,7 @@ import android.view.View;
import android.widget.Adapter; import android.widget.Adapter;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.Scroller; import android.widget.Scroller;
import com.lonelypluto.pdfviewerlibrary.R; import com.lonelypluto.pdfviewerlibrary.R;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
...@@ -108,6 +106,7 @@ public class ReaderView ...@@ -108,6 +106,7 @@ public class ReaderView
} }
public void setDisplayedViewIndex(int i) { public void setDisplayedViewIndex(int i) {
if (mAdapter != null) {
if (0 <= i && i < mAdapter.getCount()) { if (0 <= i && i < mAdapter.getCount()) {
onMoveOffChild(mCurrent); onMoveOffChild(mCurrent);
mCurrent = i; mCurrent = i;
...@@ -116,6 +115,7 @@ public class ReaderView ...@@ -116,6 +115,7 @@ public class ReaderView
requestLayout(); requestLayout();
} }
} }
}
/** /**
* 设置横向或竖向滑动 * 设置横向或竖向滑动
...@@ -590,7 +590,9 @@ public class ReaderView ...@@ -590,7 +590,9 @@ public class ReaderView
super.onLayout(changed, left, top, right, bottom); super.onLayout(changed, left, top, right, bottom);
try { try {
if (mAdapter != null) {
onLayout2(changed, left, top, right, bottom); onLayout2(changed, left, top, right, bottom);
}
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
System.out.println("Out of memory during layout"); System.out.println("Out of memory during layout");
...@@ -625,6 +627,7 @@ public class ReaderView ...@@ -625,6 +627,7 @@ public class ReaderView
return; return;
View cv = mChildViews.get(mCurrent); View cv = mChildViews.get(mCurrent);
Point cvOffset; Point cvOffset;
if (!mResetLayout) { if (!mResetLayout) {
...@@ -828,11 +831,13 @@ public class ReaderView ...@@ -828,11 +831,13 @@ public class ReaderView
private View getOrCreateChild(int i) { private View getOrCreateChild(int i) {
View v = mChildViews.get(i); View v = mChildViews.get(i);
if (v == null) { if (v == null) {
if (mAdapter != null) {
v = mAdapter.getView(i, getCached(), this); v = mAdapter.getView(i, getCached(), this);
addAndMeasureChild(i, v); addAndMeasureChild(i, v);
onChildSetup(i, v); onChildSetup(i, v);
onScaleChild(v, mScale); onScaleChild(v, mScale);
} }
}
return v; return v;
} }
...@@ -922,8 +927,14 @@ public class ReaderView ...@@ -922,8 +927,14 @@ public class ReaderView
} }
private Point subScreenSizeOffset(View v) { private Point subScreenSizeOffset(View v) {
return new Point(Math.max((getWidth() - v.getMeasuredWidth()) / 2, 0), int mw = 0;
Math.max((getHeight() - v.getMeasuredHeight()) / 2, 0)); int mh = 0;
if (v != null) {
mw = v.getMeasuredWidth();
mh = v.getMeasuredHeight();
}
return new Point(Math.max((getWidth() - mw) / 2, 0),
Math.max((getHeight() - mh) / 2, 0));
} }
private static int directionOfTravel(float vx, float vy) { private static int directionOfTravel(float vx, float vy) {
......
...@@ -23,6 +23,7 @@ import java.net.MalformedURLException; ...@@ -23,6 +23,7 @@ import java.net.MalformedURLException;
public class SavePdf { public class SavePdf {
private float defaultScale = 0.90756303f; private float defaultScale = 0.90756303f;
public void setWidthScale(float widthScale) { public void setWidthScale(float widthScale) {
this.widthScale = widthScale; this.widthScale = widthScale;
} }
...@@ -45,6 +46,7 @@ public class SavePdf { ...@@ -45,6 +46,7 @@ public class SavePdf {
/** /**
* 设置放大比例 * 设置放大比例
*
* @param scale * @param scale
*/ */
public void setScale(float scale) { public void setScale(float scale) {
...@@ -53,6 +55,7 @@ public class SavePdf { ...@@ -53,6 +55,7 @@ public class SavePdf {
/** /**
* 设置宽高 * 设置宽高
*
* @param * @param
*/ */
public void setWH(float width, float height) { public void setWH(float width, float height) {
...@@ -98,43 +101,24 @@ public class SavePdf { ...@@ -98,43 +101,24 @@ public class SavePdf {
public void addText() { public void addText() {
try { try {
PdfReader reader = new PdfReader(inPath, "PDF".getBytes());///打开要写入的PDF PdfReader reader = new PdfReader(inPath, "PDF".getBytes());///打开要写入的PDF
Log.e("addText", "1");
FileOutputStream outputStream = new FileOutputStream(outPath);//设置涂鸦后的PDF FileOutputStream outputStream = new FileOutputStream(outPath);//设置涂鸦后的PDF
Log.e("addText", "2");
PdfStamper stamp; PdfStamper stamp;
stamp = new PdfStamper(reader, outputStream); stamp = new PdfStamper(reader, outputStream);
Log.e("addText", "3 " + pageNum);
PdfContentByte over = stamp.getOverContent(pageNum);//////用于设置在第几页打印签名 PdfContentByte over = stamp.getOverContent(pageNum);//////用于设置在第几页打印签名
Log.e("addText", "4");
if (bitmap != null) {
byte[] bytes = Bitmap2Bytes(bitmap); byte[] bytes = Bitmap2Bytes(bitmap);
Image img = Image.getInstance(bytes);//将要放到PDF的图片传过来,要设置为byte[]类型 Image img = Image.getInstance(bytes);//将要放到PDF的图片传过来,要设置为byte[]类型
com.lowagie.text.Rectangle rectangle = reader.getPageSize(pageNum); com.lowagie.text.Rectangle rectangle = reader.getPageSize(pageNum);
img.setAlignment(Image.MIDDLE);// 图像在文档中的对齐方式 img.setAlignment(Image.MIDDLE);// 图像在文档中的对齐方式
img.scalePercent(rectangle.getWidth() * widthScale * 100);
//这里是重点!!!!!设置Image图片大小,需要根据屏幕的分辨率,签名时PDF的放大比例来计算;还有就是当PDF开始显示的时候,他已经做了一次缩放,可以用 rectangle.getWidth() / (bitmap.getWidth() / 2)求得那个放大比 img.setAbsolutePosition(width * (rectangle.getWidth() * widthScale) * (scale), rectangle.getHeight() - ((height) * (rectangle.getWidth() * widthScale) * (scale / defaultScale)) + img.getHeight() / 2 * widthScale * 100);
// img.scaleAbsolute(363 * 1.0f * density / 2 / scale * rectangle.getWidth() / (bitmap.getWidth() / 2), 557 * 1.0f * density / 2 / scale * rectangle.getWidth() / (bitmap.getWidth() / 2));
// img.scaleAbsolute(594 * 1.0f * density / 2 / scale * rectangle.getWidth() / (bitmap.getWidth() / 2), 557 * 1.0f * density / 2 / scale * rectangle.getWidth() / (bitmap.getWidth() / 2));
// img.scaleAbsolute(602 * 1.0f * density / 2 / scale * rectangle.getWidth() / (bitmap.getWidth() / 2), 870 * 1.0f * density / 2 / scale * rectangle.getWidth() / (bitmap.getWidth() / 2));
//这里设置image相对PDF左下角的偏移量,我的做法是得到放大后位置相对于整个PDF的百分比再乘PDF的大小得到他的相对偏移位置
// img.setAbsolutePosition(rectangle.getWidth() * widthScale, rectangle.getHeight() * heightScale);// 偏右上
Log.e("zyw", "position = " + rectangle.getWidth() * widthScale + " " + rectangle.getHeight() * heightScale);
Log.e("zyw", "density = " + density);
Log.e("zyw", "img.getWidth() = " + img.getWidth() + " img.getHeight() = " + img.getHeight());
Log.e("zyw", "scale = " + scale);
Log.e("zyw", "widthScale = " + widthScale + " heightScale = " + heightScale);
Log.e("zyw", "bitmap.w = " + bitmap.getWidth() + " bitmap.h = " + bitmap.getHeight());
Log.e("zyw", "rectangle.getLeft = " + rectangle.getLeft() + " rectangle.getBottom() = " + rectangle.getBottom());
Log.e("zyw", "rectangle.getWidth = " + rectangle.getWidth() + " rectangle.getHeight = " + rectangle.getHeight());
Log.e("zyw", "比例1 = " + ((float)rectangle.getWidth()/img.getWidth())*100);
Log.e("zyw", "比例2 = " + rectangle.getWidth() * widthScale*100);
Log.e("zyw", "坐标AbsolutePosition = " + width * (rectangle.getWidth() * widthScale) + " " + (1964-height-img.getHeight()) * (rectangle.getWidth() * widthScale));
Log.e("zyw", "差值 = " + rectangle.getHeight() * (heightScale-widthScale));
// img.scalePercent(((float)594/1080)*100);
Log.e("zyw", "缩放比例 = " + scale / defaultScale);
img.scalePercent(rectangle.getWidth() * widthScale*100);
// img.setAbsolutePosition(rectangle.getLeft(), rectangle.getBottom() - 120);
img.setAbsolutePosition(width * (rectangle.getWidth() * widthScale) * (scale ), rectangle.getHeight() - ((height) * (rectangle.getWidth() * widthScale) * (scale / defaultScale)) + img.getHeight()/2*widthScale*100);
// img.setAbsolutePosition(rectangle.getLeft() + percent/2, rectangle.getBottom() - percent/2);// 偏左下
over.addImage(img); over.addImage(img);
}
Log.e("addText", "5");
stamp.close(); stamp.close();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment