添加跳转页面。

This commit is contained in:
ocean 2025-09-25 16:14:41 +08:00
parent 456bbf5ecc
commit c03e2b2cb1
14 changed files with 322 additions and 32 deletions

View File

@ -21,6 +21,12 @@ sealed class FileActionEvent {
//只做通知不携带任何数据使用object。
object NoticeReload : FileActionEvent()
data class SetColorInversion(val b: Boolean) : FileActionEvent()
data class SetPageFling(val b: Boolean) : FileActionEvent()
data class SetSwipeVertical(val b: Boolean) : FileActionEvent()
data class GotoPage(val number: Int): FileActionEvent()
data class AddBookmark(val success: Boolean) : FileActionEvent()
data class UpdateBookmark(val success: Boolean) : FileActionEvent()
data class DeleteBookmark(val success: Boolean) : FileActionEvent()

View File

@ -98,12 +98,6 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
}
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.NoticeReload>(this) {
logDebug("observeEvent NoticeReload")
val file = File(pdfDocument.filePath)
loadPdfInternal(file, null)
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.AddBookmark>(this) {
if (it.success) {
showToast(getString(R.string.bookmark_add_success))
@ -136,6 +130,32 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
showToast(getString(R.string.removed_from_favorites))
}
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.SetPageFling>(this) { event ->
val file = File(pdfDocument.filePath)
loadPdfInternal(file, null)
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.SetColorInversion>(this) { event ->
binding.pdfview.apply {
setNightMode(event.b)
loadPages()
if (event.b) {
setBackgroundColor(getColor(R.color.night_mode_bg_color))
} else {
setBackgroundColor(getColor(R.color.grey))
}
}
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.SetSwipeVertical>(this) { event ->
val file = File(pdfDocument.filePath)
loadPdfInternal(file, null)
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.GotoPage>(this) { event ->
binding.pdfview.apply {
jumpTo(event.number - 1)
}
}
}
private fun initView() {
@ -188,7 +208,6 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
//PDF 文档加载完成时回调
override fun loadComplete(nbPages: Int) {
//加载完毕进行一次缩放
binding.pdfview.resetZoomWithAnimation()
}
@ -258,17 +277,24 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
onTap(this@PdfViewActivity) // 单击回调
onPageChange(this@PdfViewActivity) // 页面改变回调
scrollHandle(CustomScrollHandle(this@PdfViewActivity)) // 自定义的页数展示
if (appStore.isPageFling) {
pageSnap(true)//页面可在逐页中,可居中展示,非逐页模式,滑动停止后可自动定格在居中位置。
autoSpacing(true)//开启逐页就开启自动间距
pageFling(true)//逐页
autoSpacing(true)
} else {
spacing(10)
pageSnap(false)
pageFling(false)
spacing(10)
}
swipeHorizontal(!appStore.isVertical)
nightMode(appStore.isColorInversion)
}.load()
if (appStore.isColorInversion) {
binding.pdfview.setBackgroundColor(getColor(R.color.night_mode_bg_color))
} else {
binding.pdfview.setBackgroundColor(getColor(R.color.grey))
}
}
private fun toggleFullScreen() {

View File

@ -98,7 +98,7 @@ class SplitPdfActivity : BaseActivity() {
RenameType.NAME, null, item.fileName, onOkClickString = { string ->
selectedList[pos].fileName = string
selectedPdfAdapter.updateItem(pos)
}).show(supportFragmentManager, "BookmarksDialogFragment")
}).show(supportFragmentManager, "SplitPdfActivity")
}, onDeleteClick = { item, pos ->
selectedList.remove(item)
selectedPdfAdapter.removeItem(pos)

View File

@ -0,0 +1,113 @@
package com.all.pdfreader.pro.app.ui.dialog
import android.graphics.Color
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogGotoPageBinding
import com.all.pdfreader.pro.app.databinding.DialogRenameFileBinding
import com.all.pdfreader.pro.app.model.RenameType
import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
import com.all.pdfreader.pro.app.util.FileUtils
import com.all.pdfreader.pro.app.util.ToastUtils
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
import java.io.File
class GotoPageDialogFragment(
private val onOkClick: () -> Unit = {},
) : DialogFragment() {
private lateinit var binding: DialogGotoPageBinding
private val viewModel: PdfViewModel by activityViewModels()
private lateinit var pdfDocument: PdfDocumentEntity
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
binding = DialogGotoPageBinding.inflate(layoutInflater)
return binding.root
}
override fun onStart() {
super.onStart()
dialog?.window?.apply {
// 去掉系统默认的背景 padding
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
// 设置宽度为全屏减去 16dp
val margin = resources.getDimensionPixelSize(R.dimen.dialog_margin) // 16dp
val width = resources.displayMetrics.widthPixels - margin * 2
setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.pdfDocument.value?.let {
pdfDocument = it
initView()
setupOnClick()
} ?: run {
showToast(getString(R.string.file_not))
dismiss()
}
}
private fun initView() {
binding.etName.showKeyboard()
binding.tilName.hint = getString(R.string.name_must_be_number, pdfDocument.pageCount)
}
private fun setupOnClick() {
binding.tvCancel.setOnClickListener {
dismiss()
}
binding.tvConfirm.setOnClickListener {
val text = binding.etName.text.toString()
if (validateEnter(text)) {
val pageNumber = text.trim().toInt()
viewModel.gotoPage(pageNumber)
dismiss()
}
}
binding.etName.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
binding.tilName.error = null
}
override fun afterTextChanged(s: Editable?) {}
})
}
private fun validateEnter(inputText: String): Boolean {
// 不允许为空
if (inputText.isBlank()) {
binding.tilName.error = getString(R.string.name_not_empty)
return false
}
// 去掉首尾空格后转换成数字
val pageNumber = inputText.trim().toInt()
// 数字范围校验
if (pageNumber < 1 || pageNumber > pdfDocument.pageCount) {
binding.tilName.error = getString(R.string.name_out_of_range, pdfDocument.pageCount)
return false
}
return true
}
private fun showToast(message: String) {
ToastUtils.show(requireActivity(), message)
}
}

View File

@ -84,6 +84,7 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
binding.setPasswordBtn.visibility = View.VISIBLE
binding.deleteFileBtn.visibility = View.VISIBLE
binding.shareBtn.visibility = View.VISIBLE
binding.gotoPageBtn.visibility = View.GONE
}
RecentlyFrag.FRAG_TAG -> {
@ -91,6 +92,7 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
binding.setPasswordBtn.visibility = View.VISIBLE
binding.deleteFileBtn.visibility = View.VISIBLE
binding.shareBtn.visibility = View.VISIBLE
binding.gotoPageBtn.visibility = View.GONE
}
FavoriteFrag.FRAG_TAG -> {
@ -98,6 +100,7 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
binding.setPasswordBtn.visibility = View.VISIBLE
binding.deleteFileBtn.visibility = View.VISIBLE
binding.shareBtn.visibility = View.VISIBLE
binding.gotoPageBtn.visibility = View.GONE
}
PdfViewActivity.FRAG_TAG -> {
@ -105,6 +108,7 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
binding.setPasswordBtn.visibility = View.GONE
binding.deleteFileBtn.visibility = View.GONE
binding.shareBtn.visibility = View.GONE
binding.gotoPageBtn.visibility = View.VISIBLE
}
}
binding.tvFileName.text = pdfDocument.fileName
@ -212,6 +216,10 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
startActivity(intent)
dismiss()
}
binding.gotoPageBtn.setOnClickListener {
GotoPageDialogFragment().show(parentFragmentManager, "GotoPage")
dismiss()
}
}
private fun updateCollectUi(b: Boolean) {

View File

@ -82,18 +82,18 @@ class ViewModelDialogFragment() : BottomSheetDialogFragment() {
binding.btnHorizontal.setOnClickListener {
setSelectedMode(isVertical = false)
AppStore(requireActivity()).isVertical = false
viewModel.noticeReloadPdf()
viewModel.setSwipeVertical(false)
}
binding.btnVertical.setOnClickListener {
setSelectedMode(isVertical = true)
AppStore(requireActivity()).isVertical = true
viewModel.noticeReloadPdf()
viewModel.setSwipeVertical(true)
}
binding.switchPageByPage.setOnCheckedChangeListener(object : OnCheckedChangeListener {
override fun onCheckedChanged(view: CustomSwitchButton?, isChecked: Boolean) {
view?.setChecked(isChecked)
appstore.isPageFling = isChecked
viewModel.noticeReloadPdf()
viewModel.setPageFling(appstore.isPageFling)
}
})
binding.switchColorInversion.setOnCheckedChangeListener(object : OnCheckedChangeListener {
@ -103,7 +103,7 @@ class ViewModelDialogFragment() : BottomSheetDialogFragment() {
) {
view?.setChecked(isChecked)
appstore.isColorInversion = isChecked
viewModel.noticeReloadPdf()
viewModel.setColorInversion(appstore.isColorInversion)
}
})
}

View File

@ -196,6 +196,30 @@ class PdfViewModel : ViewModel() {
}
}
fun setColorInversion(b: Boolean) {
viewModelScope.launch {
_fileActionEvent.postValue(FileActionEvent.SetColorInversion(b))
}
}
fun setSwipeVertical(b: Boolean) {
viewModelScope.launch {
_fileActionEvent.postValue(FileActionEvent.SetSwipeVertical(b))
}
}
fun setPageFling(b: Boolean) {
viewModelScope.launch {
_fileActionEvent.postValue(FileActionEvent.SetPageFling(b))
}
}
fun gotoPage(number: Int){
viewModelScope.launch {
_fileActionEvent.postValue(FileActionEvent.GotoPage(number))
}
}
fun removeRecent(filePath: String) {
viewModelScope.launch {
pdfRepository.updateLastOpenTime(filePath, 0L)

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M874.7,544c-17.1,0 -32,14.9 -32,32v256c0,6.4 -4.3,10.7 -10.7,10.7H192c-6.4,0 -10.7,-4.3 -10.7,-10.7V192c0,-6.4 4.3,-10.7 10.7,-10.7h256c17.1,0 32,-14.9 32,-32s-14.9,-32 -32,-32H192C151.5,117.3 117.3,151.5 117.3,192v640c0,40.5 34.1,74.7 74.7,74.7h640c40.5,0 74.7,-34.1 74.7,-74.7V576c0,-17.1 -14.9,-32 -32,-32z"
android:fillColor="#666666"/>
<path
android:pathData="M874.7,117.3H640c-17.1,0 -32,14.9 -32,32s14.9,32 32,32h157.9L509.9,467.2c-12.8,12.8 -12.8,32 0,44.8 6.4,6.4 14.9,8.5 23.5,8.5s17.1,-2.1 23.5,-8.5l285.9,-285.9V384c0,17.1 14.9,32 32,32s32,-14.9 32,-32V149.3c0,-17.1 -14.9,-32 -32,-32z"
android:fillColor="#666666"/>
</vector>

View File

@ -4,9 +4,6 @@
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M874.7,544c-17.1,0 -32,14.9 -32,32v256c0,6.4 -4.3,10.7 -10.7,10.7H192c-6.4,0 -10.7,-4.3 -10.7,-10.7V192c0,-6.4 4.3,-10.7 10.7,-10.7h256c17.1,0 32,-14.9 32,-32s-14.9,-32 -32,-32H192C151.5,117.3 117.3,151.5 117.3,192v640c0,40.5 34.1,74.7 74.7,74.7h640c40.5,0 74.7,-34.1 74.7,-74.7V576c0,-17.1 -14.9,-32 -32,-32z"
android:fillColor="#666666"/>
<path
android:pathData="M874.7,117.3H640c-17.1,0 -32,14.9 -32,32s14.9,32 32,32h157.9L509.9,467.2c-12.8,12.8 -12.8,32 0,44.8 6.4,6.4 14.9,8.5 23.5,8.5s17.1,-2.1 23.5,-8.5l285.9,-285.9V384c0,17.1 14.9,32 32,32s32,-14.9 32,-32V149.3c0,-17.1 -14.9,-32 -32,-32z"
android:pathData="M768.7,703.5c-35.6,0 -67.9,14.8 -91.2,38.4l-309.1,-171.7c9.1,-17.5 14.6,-37.2 14.6,-58.3 0,-12.6 -2.4,-24.4 -5.7,-36l304.6,-189.2c22.7,20.5 52.5,33.2 85.1,33.2 70.5,0 128,-57.5 128,-128S837.7,64 767.2,64s-128,57.5 -128,128c0,14.6 2.9,28.4 7.4,41.5L344.7,420.7c-23,-22.7 -54.7,-37 -89.8,-37 -70.5,0 -128,57.5 -128,128s57.5,128 128,128c25.6,0 49.5,-7.7 69.5,-20.8l321.2,178.4c-3.1,11 -5.2,22.2 -5.2,34.1 0,70.5 57.5,128 128,128s128,-57.5 128,-128S839.3,703.5 768.7,703.5zM767.2,128c35.3,0 64,28.7 64,64s-28.7,64 -64,64 -64,-28.7 -64,-64S731.9,128 767.2,128zM191.1,511.9c0,-35.3 28.7,-64 64,-64s64,28.7 64,64 -28.7,64 -64,64S191.1,547.2 191.1,511.9zM768.7,895.5c-35.3,0 -64,-28.7 -64,-64s28.7,-64 64,-64 64,28.7 64,64C832.7,867 804,895.5 768.7,895.5z"
android:fillColor="#666666"/>
</vector>

View File

@ -80,13 +80,6 @@
android:layout_height="match_parent"
android:background="@color/grey" />
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfview2"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey" />
</RelativeLayout>
<LinearLayout

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/dr_rounded_corner_12_bg_white"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
style="@style/TextViewFont_PopMedium"
android:text="@string/go_to_page"
android:textColor="@color/black"
android:textSize="20sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextViewFont_PopRegular"
android:layout_marginBottom="16dp"
android:text="@string/go_to_page_desc"
android:textColor="@color/black_60"
android:textSize="16sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/name_must_be_number"
app:endIconDrawable="@drawable/delete"
app:endIconMode="clear_text">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
style="@style/TextViewFont_PopRegular"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="horizontal">
<TextView
android:id="@+id/tvCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
style="@style/TextViewFont_PopRegular"
android:padding="12dp"
android:text="@string/cancel"
android:textColor="@color/black_80" />
<TextView
android:id="@+id/tvConfirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextViewFont_PopSemiBold"
android:padding="12dp"
android:text="@string/go_to_page"
android:textColor="@color/black" />
</LinearLayout>
</LinearLayout>

View File

@ -63,10 +63,10 @@
<TextView
android:id="@+id/tvFileName"
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="middle"
style="@style/TextViewFont_PopMedium"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/grey_text_color"
@ -80,19 +80,19 @@
<TextView
android:id="@+id/tvFileDate"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextViewFont_PopRegular"
android:text="@string/app_name"
android:textColor="@color/black_60"
android:textSize="14sp" />
<TextView
android:id="@+id/tvFileSize"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/app_name"
android:textColor="@color/black_60"
android:textSize="14sp" />
@ -123,6 +123,30 @@
android:layout_marginEnd="16dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/gotoPageBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/goto_page" />
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/go_to_page"
android:textColor="@color/grey_text_color"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/renameFileBtn"
android:layout_width="0dp"
@ -137,10 +161,10 @@
android:src="@drawable/rename_text" />
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/rename_file"
android:textColor="@color/grey_text_color"
android:textSize="14sp" />
@ -160,10 +184,10 @@
android:src="@drawable/prompt" />
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/file_details"
android:textColor="@color/grey_text_color"
android:textSize="14sp" />
@ -183,10 +207,10 @@
android:src="@drawable/share" />
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/share_file"
android:textColor="@color/grey_text_color"
android:textSize="14sp" />
@ -206,10 +230,10 @@
android:src="@drawable/print" />
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/print_pdf"
android:textColor="@color/grey_text_color"
android:textSize="14sp" />

View File

@ -24,4 +24,5 @@
<color name="btn_sel_on_color">#E43521</color>
<color name="btn_sel_off_color">#33E43521</color>
<color name="placeholder_bg_color">#E8EAEE</color>
<color name="night_mode_bg_color">#A6000000</color>
</resources>

View File

@ -136,4 +136,8 @@
<string name="please_select_page">Please select at least one page</string>
<string name="splitting">Splitting…</string>
<string name="search_hint">Search……</string>
<string name="go_to_page">Goto page</string>
<string name="go_to_page_desc">Quickly navigate to any page in the file.</string>
<string name="name_must_be_number">Please enter a number(1-%1$d)</string>
<string name="name_out_of_range">Please enter a number between 1 and %1$d</string>
</resources>