Commit c30c7593 authored by wanglei's avatar wanglei

...

parent ec932d27
......@@ -15,6 +15,16 @@ android {
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// ndk {
// abiFilters.add("arm64-v8a")
// // 取消注释以下行以添加更多 ABI 支持
// abiFilters.add("armeabi-v7a")
// }
// sourceSets {
// getByName("main") {
// jniLibs.srcDirs("src/main/jniLibs")
// }
// }
}
buildTypes {
......@@ -34,13 +44,8 @@ android {
viewBinding = true
buildConfig = true
}
sourceSets {
getByName("main") {
assets {
srcDirs("src\\main\\assets", "src\\main\\assets")
}
}
}
}
dependencies {
......
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.util.DisplayMetrics
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.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.base.pdfviewerscannerwhite.bean.PdfPageBean
import com.base.pdfviewerscannerwhite.databinding.ActivityPdfBinding
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 java.io.File
......@@ -14,10 +34,15 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
private lateinit var pdfPresenter: PdfPresenter
private lateinit var pdfPageAdapter: PdfPagerAdapter
private var muPDFCore: MuPDFCore? = null // 加载mupdf.so文件
private var searchTask: SearchTask? = null
private var uiMode = UI_MODE_NORMAL
private var saveMode = ""
private var path: String = ""
private var density = 0f
override val binding: ActivityPdfBinding by lazy {
ActivityPdfBinding.inflate(layoutInflater)
......@@ -26,29 +51,323 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
override fun initView() {
val metrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(metrics)
density = metrics.density
path = intent.extras?.getString("path") ?: ""
val file = File(path)
binding.tvPdfName.text = file.name
pdfPresenter = PdfPresenter(this, this)
initAdapter()
changeNormalUI()
muPDFCore = pdfPresenter.openFile(path)
// 搜索设为空
SearchTaskResult.set(null)
if (muPDFCore == null) {
toast("can't open pdf")
} else {
pdfPresenter.iniPdfPage(path)
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
}
createPdfUI()
changeEditSelectUI(binding.llHighlight)
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
}
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
*/
@SuppressLint("SetTextI18n")
private fun createPdfUI() {
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 {
/**
* 编辑选择UI模式
*/
fun changeEditSelectUI(view: View) {
private fun changeEditSelectUI(view: View) {
uiMode = UI_MODE_EDITE_SELECT
binding.tvBtnSave.visibility = View.GONE
......@@ -65,7 +384,6 @@ class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
binding.ivSearch.visibility = View.INVISIBLE
binding.ivMore.visibility = View.INVISIBLE
binding.clOperation.visibility = View.VISIBLE
binding.ivWancheng.visibility = View.VISIBLE
if (binding.llHighlight == view) {
......@@ -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 {
const val UI_MODE_NORMAL = 0
const val UI_MODE_SEARCH = 1
const val UI_MODE_EDITE_SAVE = 2
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>) {
pdfPageAdapter.submitList(items)
pdfPageAdapter.changeSelectPager(0)
}
}
\ No newline at end of file
......@@ -2,21 +2,21 @@ package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.content.Intent
import androidx.lifecycle.lifecycleScope
import com.artifex.mupdfdemo.MuPDFCore
import com.base.pdfviewerscannerwhite.databinding.ActivityPdfLoadingBinding
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.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.io.File
import kotlin.random.Random
class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
private val TAG = "PdfLoadingActivity"
private var doWhat = ""
private var srcPath: String = ""
private var newName: String = ""
private var newPath: String = ""
private var splitIndex: List<Int> = listOf()
private lateinit var pdfPresenter: PdfPresenter
......@@ -24,16 +24,36 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
ActivityPdfLoadingBinding.inflate(layoutInflater)
}
var isFinishBoolean: Boolean = false
var newPdfFile: File? = null
private var isFinishBoolean: Boolean = false
private var progressFinishAction: (() -> Unit)? = null
override fun initView() {
pdfPresenter = PdfPresenter(this)
initSpPa()
pdfPresenter.splitPdf(File(srcPath), newName, splitIndex, finishAction = {
newPdfFile = it
isFinishBoolean = true
})
when (doWhat) {
DO_SPLIT_PDF -> {
progressFinishAction = {
finish()
}
pdfPresenter.splitPdf(srcPath, newPath, splitIndex, finishAction = {
isFinishBoolean = true
})
}
DO_SAVE_PDF -> {
muPDFCore?.save()
muPDFCore = null
progressFinishAction = {
finish()
}
lifecycleScope.launch {
delay(Random.nextLong(1500, 2500))
isFinishBoolean = true
}
}
}
startProgress()
}
......@@ -49,18 +69,22 @@ class PdfLoadingActivity : BaseActivity<ActivityPdfLoadingBinding>() {
}
delay(500)
}
if (newPdfFile == null) {
toast("split pdf failed!")
finish()
return@launch
}
progressFinishAction?.invoke()
}
private fun initSpPa() {
doWhat = intent?.extras?.getString("doWhat", "") ?: ""
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()
}
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
runCatching {
val drawable = PdfBoxUtils.getPdfDrawablePage(context, pdfPath, item.pageIndex, scale)
item.pageDrawable = drawable
// 任务代码
itemView.post {
item.pageDrawable?.let {
iv.setImageDrawable(it)
......
package com.base.pdfviewerscannerwhite.ui.document.pdf
import android.content.Context
import android.os.Handler
import android.util.Log
import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.OutlineActivityData
import com.base.pdfviewerscannerwhite.bean.PdfPageBean
......@@ -15,14 +13,12 @@ class PdfPresenter(
val context: Context,
val pdfView: PdfView? = null
) {
var handler: Handler? = null
private val TAG = "PdfPresenter"
fun openFile(path: String): MuPDFCore? {
val muPDFCore: MuPDFCore? = null
var muPDFCore: MuPDFCore? = null
try {
MuPDFCore(context, path)
muPDFCore = MuPDFCore(context, path)
// 新建:删除旧的目录数据
OutlineActivityData.set(null)
} catch (e: java.lang.Exception) {
......@@ -44,13 +40,13 @@ class PdfPresenter(
}
fun splitPdf(
file: File, newName: String, splitIndex: List<Int>,
srcPath: String, newPath: String, splitIndex: List<Int>,
finishAction: (newFile: File?) -> Unit
) = Thread {
val newFile = File(file.parentFile, newName)
try {
// 加载现有 PDF 文档
val sourceDocument = PDDocument.load(file)
val sourceDocument = PDDocument.load(File(srcPath))
// 创建新的 PDF 文档
val newDocument = PDDocument()
......@@ -61,7 +57,7 @@ class PdfPresenter(
newDocument.addPage(page)
}
// 保存新的 PDF 文档
newDocument.save(newFile)
newDocument.save(newPath)
newDocument.close()
sourceDocument.close()
} catch (e: Exception) {
......@@ -69,6 +65,48 @@ class PdfPresenter(
finishAction.invoke(null)
return@Thread
}
finishAction.invoke(newFile)
finishAction.invoke(File(newPath))
}.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 @@
android:layout_height="match_parent"
tools:context=".ui.document.pdf.PdfActivity">
<!-- <com.artifex.mupdfdemo.MuPDFReaderView-->
<!-- android:id="@+id/mupdf_reader_view"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent" />-->
<com.artifex.mupdfdemo.MuPDFReaderView
android:id="@+id/mupdf_reader_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ViewAnimator
android:id="@+id/v_animator_top"
......@@ -134,7 +135,7 @@
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/iv_xuanzhuan"
app:layout_constraintEnd_toEndOf="@+id/iv_more"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
......@@ -142,10 +143,27 @@
</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
android:id="@+id/v_animator_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent">
......@@ -160,14 +178,17 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingVertical="8dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/v_animator_bottom">
<LinearLayout
android:id="@+id/ll_highlight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_glide_line"
app:layout_constraintStart_toStartOf="parent"
......@@ -194,8 +215,10 @@
<LinearLayout
android:id="@+id/ll_glide_line"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_strikethrough"
app:layout_constraintStart_toEndOf="@id/ll_highlight"
......@@ -222,8 +245,10 @@
<LinearLayout
android:id="@+id/ll_strikethrough"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_painting_brush"
app:layout_constraintStart_toEndOf="@id/ll_glide_line"
......@@ -252,6 +277,7 @@
android:id="@+id/ll_painting_brush"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ll_strikethrough"
......@@ -294,4 +320,16 @@
</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>
\ No newline at end of file
......@@ -40,7 +40,6 @@
android:layout_marginHorizontal="56dp"
android:layout_marginTop="19dp"
android:max="100"
android:progress="50"
android:progressDrawable="@drawable/progress_bg"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
......
......@@ -4,11 +4,23 @@ plugins {
id 'org.jetbrains.kotlin.android'
}
android {
compileSdkVersion 28
namespace "com.lonelypluto.pdfviewerlibrary"
compileSdk 34
defaultConfig {
minSdkVersion 17
minSdk 24
targetSdk 34
ndk {
abiFilters "arm64-v8a"
// "armeabi-v7a"
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
}
buildTypes {
......@@ -25,6 +37,5 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// implementation 'com.android.support:appcompat-v7:28.0.0'
implementation(libs.androidx.appcompat)
}
\ No newline at end of file
......@@ -4,7 +4,9 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
import java.util.ArrayList;
import com.lonelypluto.pdfviewerlibrary.R;
public class MuPDFCore {
......@@ -12,17 +14,23 @@ public class MuPDFCore {
private static boolean gs_so_available = false;
static {
System.out.println("Loading dll");
System.loadLibrary("mupdf_java");
System.out.println("Loaded dll");
if (gprfSupportedInternal()) {
try {
System.loadLibrary("gs");
gs_so_available = true;
} catch (UnsatisfiedLinkError e) {
gs_so_available = false;
try {
System.out.println("Loading dll");
System.loadLibrary("mupdf_java");
System.out.println("Loaded dll");
Boolean flag = gprfSupportedInternal();
if (flag) {
try {
System.loadLibrary("gs");
gs_so_available = true;
} catch (UnsatisfiedLinkError e) {
gs_so_available = false;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/* Readable members */
......
......@@ -14,9 +14,7 @@ import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.Scroller;
import com.lonelypluto.pdfviewerlibrary.R;
import java.util.LinkedList;
import java.util.NoSuchElementException;
......@@ -108,12 +106,14 @@ public class ReaderView
}
public void setDisplayedViewIndex(int i) {
if (0 <= i && i < mAdapter.getCount()) {
onMoveOffChild(mCurrent);
mCurrent = i;
onMoveToChild(i);
mResetLayout = true;
requestLayout();
if (mAdapter != null) {
if (0 <= i && i < mAdapter.getCount()) {
onMoveOffChild(mCurrent);
mCurrent = i;
onMoveToChild(i);
mResetLayout = true;
requestLayout();
}
}
}
......@@ -590,7 +590,9 @@ public class ReaderView
super.onLayout(changed, left, top, right, bottom);
try {
onLayout2(changed, left, top, right, bottom);
if (mAdapter != null) {
onLayout2(changed, left, top, right, bottom);
}
} catch (OutOfMemoryError e) {
System.out.println("Out of memory during layout");
......@@ -625,6 +627,7 @@ public class ReaderView
return;
View cv = mChildViews.get(mCurrent);
Point cvOffset;
if (!mResetLayout) {
......@@ -828,10 +831,12 @@ public class ReaderView
private View getOrCreateChild(int i) {
View v = mChildViews.get(i);
if (v == null) {
v = mAdapter.getView(i, getCached(), this);
addAndMeasureChild(i, v);
onChildSetup(i, v);
onScaleChild(v, mScale);
if (mAdapter != null) {
v = mAdapter.getView(i, getCached(), this);
addAndMeasureChild(i, v);
onChildSetup(i, v);
onScaleChild(v, mScale);
}
}
return v;
......@@ -922,8 +927,14 @@ public class ReaderView
}
private Point subScreenSizeOffset(View v) {
return new Point(Math.max((getWidth() - v.getMeasuredWidth()) / 2, 0),
Math.max((getHeight() - v.getMeasuredHeight()) / 2, 0));
int mw = 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) {
......
......@@ -23,6 +23,7 @@ import java.net.MalformedURLException;
public class SavePdf {
private float defaultScale = 0.90756303f;
public void setWidthScale(float widthScale) {
this.widthScale = widthScale;
}
......@@ -40,11 +41,12 @@ public class SavePdf {
private float scale;
private float density; ///手机屏幕的分辨率密度
private float width;
private float height;
private float width;
private float height;
/**
* 设置放大比例
*
* @param scale
*/
public void setScale(float scale) {
......@@ -53,6 +55,7 @@ public class SavePdf {
/**
* 设置宽高
*
* @param
*/
public void setWH(float width, float height) {
......@@ -98,43 +101,24 @@ public class SavePdf {
public void addText() {
try {
PdfReader reader = new PdfReader(inPath, "PDF".getBytes());///打开要写入的PDF
Log.e("addText", "1");
FileOutputStream outputStream = new FileOutputStream(outPath);//设置涂鸦后的PDF
Log.e("addText", "2");
PdfStamper stamp;
stamp = new PdfStamper(reader, outputStream);
Log.e("addText", "3 " + pageNum);
PdfContentByte over = stamp.getOverContent(pageNum);//////用于设置在第几页打印签名
byte[] bytes = Bitmap2Bytes(bitmap);
Image img = Image.getInstance(bytes);//将要放到PDF的图片传过来,要设置为byte[]类型
com.lowagie.text.Rectangle rectangle = reader.getPageSize(pageNum);
img.setAlignment(Image.MIDDLE);// 图像在文档中的对齐方式
//这里是重点!!!!!设置Image图片大小,需要根据屏幕的分辨率,签名时PDF的放大比例来计算;还有就是当PDF开始显示的时候,他已经做了一次缩放,可以用 rectangle.getWidth() / (bitmap.getWidth() / 2)求得那个放大比
// 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);
Log.e("addText", "4");
if (bitmap != null) {
byte[] bytes = Bitmap2Bytes(bitmap);
Image img = Image.getInstance(bytes);//将要放到PDF的图片传过来,要设置为byte[]类型
com.lowagie.text.Rectangle rectangle = reader.getPageSize(pageNum);
img.setAlignment(Image.MIDDLE);// 图像在文档中的对齐方式
img.scalePercent(rectangle.getWidth() * widthScale * 100);
img.setAbsolutePosition(width * (rectangle.getWidth() * widthScale) * (scale), rectangle.getHeight() - ((height) * (rectangle.getWidth() * widthScale) * (scale / defaultScale)) + img.getHeight() / 2 * widthScale * 100);
over.addImage(img);
}
Log.e("addText", "5");
stamp.close();
} catch (FileNotFoundException e) {
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