diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt index c26127e..9c649de 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/act/PdfViewActivity.kt @@ -79,31 +79,24 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList appStore.isEyeCareMode = !appStore.isEyeCareMode toggleEyeCareMode(appStore.isEyeCareMode) } + binding.viewModelBtn.setOnClickListener { + + } } private fun loadPdf() { logDebug("loadPdf ->${pdfDocument.lastReadPage} ${pdfDocument.readingProgress}") // 使用传递的文件路径加载PDF val file = File(pdfDocument.filePath) - if (file.exists()) { - //需要密码展示对话框。 - if (pdfDocument.isPassword) { - showPasswordDialog(file) - return - } - // 无密码PDF正常加载 - binding.pdfview.fromFile(file).defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始 - .enableDoubletap(true)// 是否允许双击缩放 - .onLoad(this)//加载 - .enableAnnotationRendering(true) // 是否渲染注释(如评论、颜色、表单等) - .onError(this)//错误 - .onTap(this)//点击 - .onPageChange(this)//页面改变 - .scrollHandle(CustomScrollHandle(this))//自定义的页数展示,并且可快速拖动 - .load() - } else { + if (!file.exists()) { showToast(getString(R.string.file_not) + ": ${pdfDocument.fileName}") finish() + return + } + if (pdfDocument.isPassword) { + showPasswordDialog(file) + } else { + loadPdfInternal(file, null) // 无密码 } } @@ -164,15 +157,23 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList } private fun tryLoadPdfWithPassword(file: File, password: String) { - binding.pdfview.fromFile(file).password(password) // 使用输入的密码 - .defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始 - .enableDoubletap(true)// 是否允许双击缩放 - .onLoad(this)//加载 - .onTap(this)//单击 - .enableAnnotationRendering(true) // 是否渲染注释(如评论、颜色、表单等) - .onError(this)//错误 - .onPageChange(this)//页面改变 - .scrollHandle(CustomScrollHandle(this))//自定义的页数展示,并且可快速拖动 + loadPdfInternal(file, password) // 传入密码 + } + + private fun loadPdfInternal(file: File, password: String?) { + binding.pdfview.fromFile(file) + .apply { + password?.let { password(it) } // 只有在有密码时才调用 + defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始 + enableDoubletap(true) // 是否允许双击缩放 + enableAnnotationRendering(true) // 是否渲染注释 + onLoad(this@PdfViewActivity) // 加载回调 + onError(this@PdfViewActivity) // 错误回调 + onTap(this@PdfViewActivity) // 单击回调 + onPageChange(this@PdfViewActivity) // 页面改变回调 + scrollHandle(CustomScrollHandle(this@PdfViewActivity)) // 自定义的页数展示 + pageFling(true)//逐页滑动 + } .load() } diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt index 0b2e855..90abfae 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ListMoreDialogFragment.kt @@ -31,6 +31,11 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() private lateinit var pdfDocument: PdfDocumentEntity private var isFavorite: Boolean = false + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { @@ -41,7 +46,7 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() override fun onStart() { super.onStart() dialog?.window?.findViewById(com.google.android.material.R.id.design_bottom_sheet) - ?.setBackgroundResource(R.drawable.dr_rounded_corner_12_bg_white) + ?.setBackgroundResource(R.drawable.dr_rc_top_12_bg_white) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -60,6 +65,10 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() viewModel.getPDFDocument(filePath) } + override fun onDestroy() { + super.onDestroy() + } + private fun initUi() { binding.tvFileName.text = pdfDocument.fileName binding.tvFileSize.text = pdfDocument.fileSize.toFormatFileSize() @@ -105,19 +114,29 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment() val result = printPdfFile(requireActivity(), Uri.fromFile(File(pdfDocument.filePath))) when (result) { PrintResult.DeviceNotSupported -> { - Toast.makeText(context, R.string.device_does_not_support_printing, Toast.LENGTH_LONG).show() + Toast.makeText( + context, + R.string.device_does_not_support_printing, + Toast.LENGTH_LONG + ).show() } is PrintResult.Error -> { - Toast.makeText(context, R.string.pdf_cannot_print_error, Toast.LENGTH_LONG).show() + Toast.makeText(context, R.string.pdf_cannot_print_error, Toast.LENGTH_LONG) + .show() } PrintResult.MalformedPdf -> { - Toast.makeText(context, R.string.cannot_print_malformed_pdf, Toast.LENGTH_LONG).show() + Toast.makeText(context, R.string.cannot_print_malformed_pdf, Toast.LENGTH_LONG) + .show() } PrintResult.PasswordRequired -> { - Toast.makeText(context, R.string.pdf_cant_print_password_protected, Toast.LENGTH_LONG).show() + Toast.makeText( + context, + R.string.pdf_cant_print_password_protected, + Toast.LENGTH_LONG + ).show() } PrintResult.Success -> { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/PermissionDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/PermissionDialogFragment.kt index c11c654..5031a85 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/PermissionDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/PermissionDialogFragment.kt @@ -8,6 +8,7 @@ import android.os.Build import android.os.Bundle import android.provider.Settings import android.view.Gravity +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts @@ -19,8 +20,9 @@ import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.databinding.DialogPermissionBinding import com.all.pdfreader.pro.app.sp.AppStore import com.all.pdfreader.pro.app.util.StoragePermissionHelper +import com.google.android.material.bottomsheet.BottomSheetDialogFragment -class PermissionDialogFragment : DialogFragment() { +class PermissionDialogFragment : BottomSheetDialogFragment() { private lateinit var binding: DialogPermissionBinding @@ -34,13 +36,26 @@ class PermissionDialogFragment : DialogFragment() { } } - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val dialog = Dialog(requireContext(), R.style.BottomSheetDialogStyle) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { binding = DialogPermissionBinding.inflate(layoutInflater) - dialog.setContentView(binding.root) - AppStore(requireActivity()).isShowPermissionsDialogPrompt = true + return binding.root + } + + override fun onStart() { + super.onStart() + dialog?.window?.findViewById(com.google.android.material.R.id.design_bottom_sheet) + ?.setBackgroundResource(R.drawable.dr_rc_top_12_bg_white) // 设置对话框在底部显示并左右铺满 - dialog.window?.let { window -> + dialog?.window?.let { window -> window.setLayout( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT @@ -48,9 +63,13 @@ class PermissionDialogFragment : DialogFragment() { window.setGravity(Gravity.BOTTOM) window.setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) } + dialog?.setCancelable(false) + dialog?.setCanceledOnTouchOutside(false) + } - dialog.setCancelable(false) - dialog.setCanceledOnTouchOutside(false) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + AppStore(requireActivity()).isShowPermissionsDialogPrompt = true binding.prDesc.text = getString(R.string.permission_required_desc_1, getString(R.string.app_name)) @@ -68,7 +87,6 @@ class PermissionDialogFragment : DialogFragment() { dismiss() (activity as? CloseCallback)?.onClose() } - return dialog } private fun checkPermissions(): Boolean { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/SortDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/SortDialogFragment.kt index 144eff3..8809c10 100644 --- a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/SortDialogFragment.kt +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/SortDialogFragment.kt @@ -24,6 +24,11 @@ class SortDialogFragment( private lateinit var selectedField: SortField private lateinit var selectedDirection: SortDirection + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { @@ -34,7 +39,7 @@ class SortDialogFragment( override fun onStart() { super.onStart() dialog?.window?.findViewById(com.google.android.material.R.id.design_bottom_sheet) - ?.setBackgroundResource(R.drawable.dr_rounded_corner_12_bg_white) + ?.setBackgroundResource(R.drawable.dr_rc_top_12_bg_white) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt new file mode 100644 index 0000000..7d3a1da --- /dev/null +++ b/app/src/main/java/com/all/pdfreader/pro/app/ui/dialog/ViewModelDialogFragment.kt @@ -0,0 +1,187 @@ +package com.all.pdfreader.pro.app.ui.dialog + +import android.net.Uri +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.activityViewModels +import com.all.pdfreader.pro.app.R +import com.all.pdfreader.pro.app.databinding.DialogListMoreBinding +import com.all.pdfreader.pro.app.databinding.DialogViewModelBinding +import com.all.pdfreader.pro.app.model.PrintResult +import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity +import com.all.pdfreader.pro.app.util.AppUtils.dpToPx +import com.all.pdfreader.pro.app.util.AppUtils.printPdfFile +import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation +import com.all.pdfreader.pro.app.util.AppUtils.shareFile +import com.all.pdfreader.pro.app.util.FileUtils.toFormatFileSize +import com.all.pdfreader.pro.app.util.FileUtils.toSlashDate +import com.all.pdfreader.pro.app.viewmodel.PdfViewModel +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.bitmap.CenterCrop +import com.bumptech.glide.load.resource.bitmap.RoundedCorners +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import java.io.File + +class ViewModelDialogFragment(val filePath: String) : BottomSheetDialogFragment() { + + private lateinit var binding: DialogViewModelBinding + private val viewModel: PdfViewModel by activityViewModels() + private lateinit var pdfDocument: PdfDocumentEntity + private var isFavorite: Boolean = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + /** + * 让 BottomSheetDialogFragment 覆盖底部导航栏 + * 原理: + * 1.自定义样式,并继承自 @style/Theme.Design.BottomSheetDialog + * 2.xml布局设置fitsSystemWindows + */ + setStyle(STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? + ): View? { + binding = DialogViewModelBinding.inflate(layoutInflater) + return binding.root + } + + override fun onStart() { + super.onStart() + dialog?.window?.findViewById(com.google.android.material.R.id.design_bottom_sheet) + ?.setBackgroundResource(R.drawable.dr_rc_top_12_bg_white) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + viewModel.pdfDocument.observe(this) { document -> + document?.let { + pdfDocument = it + isFavorite = pdfDocument.isFavorite + initUi() + setupOnClick() + } ?: run { + showToast(getString(R.string.file_not)) + dismiss() + } + } + viewModel.getPDFDocument(filePath) + } + + private fun initUi() { + binding.tvFileName.text = pdfDocument.fileName + binding.tvFileSize.text = pdfDocument.fileSize.toFormatFileSize() + binding.tvFileDate.text = pdfDocument.lastModified.toSlashDate() + if (pdfDocument.isPassword) { + binding.lockLayout.visibility = View.VISIBLE + binding.tvFileImg.visibility = View.GONE + } else { + binding.lockLayout.visibility = View.GONE + binding.tvFileImg.visibility = View.VISIBLE + Glide.with(binding.root).load(pdfDocument.thumbnailPath) + .transform(CenterCrop(), RoundedCorners(8.dpToPx(binding.root.context))) + .into(binding.tvFileImg) + } + updateCollectUi(isFavorite) + updatePasswordUi(pdfDocument.isPassword) + } + + private fun setupOnClick() { + binding.collectBtn.setClickWithAnimation(duration = 250) { + isFavorite = !isFavorite + updateCollectUi(isFavorite) + viewModel.saveCollectState(pdfDocument.filePath, isFavorite) + dismiss() + } + binding.renameFileBtn.setOnClickListener { + RenameDialogFragment().show(parentFragmentManager, "ListMoreDialogFragment") + dismiss() + } + binding.deleteFileBtn.setOnClickListener { + DeleteDialogFragment().show(parentFragmentManager, "DeleteDialogFragment") + dismiss() + } + binding.detailsBtn.setOnClickListener { + FileDetailsDialogFragment().show(parentFragmentManager, "FileDetailsDialogFragment") + dismiss() + } + binding.shareBtn.setOnClickListener { + shareFile(requireActivity(), File(pdfDocument.filePath)) + dismiss() + } + binding.printBtn.setOnClickListener { + val result = printPdfFile(requireActivity(), Uri.fromFile(File(pdfDocument.filePath))) + when (result) { + PrintResult.DeviceNotSupported -> { + Toast.makeText( + context, + R.string.device_does_not_support_printing, + Toast.LENGTH_LONG + ).show() + } + + is PrintResult.Error -> { + Toast.makeText(context, R.string.pdf_cannot_print_error, Toast.LENGTH_LONG) + .show() + } + + PrintResult.MalformedPdf -> { + Toast.makeText(context, R.string.cannot_print_malformed_pdf, Toast.LENGTH_LONG) + .show() + } + + PrintResult.PasswordRequired -> { + Toast.makeText( + context, + R.string.pdf_cant_print_password_protected, + Toast.LENGTH_LONG + ).show() + } + + PrintResult.Success -> { + + } + } + dismiss() + } + binding.duplicateFileBtn.setOnClickListener { + viewModel.duplicateFile(requireActivity(), pdfDocument.filePath) + dismiss() + } + binding.setPasswordBtn.setOnClickListener { + if (pdfDocument.isPassword) { + PdfRemovePasswordDialog().show(parentFragmentManager, "PdfRemovePasswordDialog") + } else { + PdfSetPasswordDialog().show(parentFragmentManager, "PdfSetPasswordDialog") + } + dismiss() + } + } + + private fun updateCollectUi(b: Boolean) { + if (b) { + binding.collectIv.setImageResource(R.drawable.collected) + } else { + binding.collectIv.setImageResource(R.drawable.collect) + } + } + + private fun updatePasswordUi(b: Boolean) { + if (b) { + binding.passwordIv.setImageResource(R.drawable.unlock) + binding.passwordTv.text = getString(R.string.remove_password) + } else { + binding.passwordIv.setImageResource(R.drawable.lock) + binding.passwordTv.text = getString(R.string.set_password) + } + } + + private fun showToast(message: String) { + Toast.makeText(requireActivity(), message, Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/add_bookmarks.xml b/app/src/main/res/drawable/add_bookmarks.xml new file mode 100644 index 0000000..be6c50e --- /dev/null +++ b/app/src/main/res/drawable/add_bookmarks.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/dr_rc_top_12_bg_white.xml b/app/src/main/res/drawable/dr_rc_top_12_bg_white.xml new file mode 100644 index 0000000..4314e20 --- /dev/null +++ b/app/src/main/res/drawable/dr_rc_top_12_bg_white.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/eye_protect.xml b/app/src/main/res/drawable/eye_protect.xml index d466c77..1db7e40 100644 --- a/app/src/main/res/drawable/eye_protect.xml +++ b/app/src/main/res/drawable/eye_protect.xml @@ -1,6 +1,21 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/pdf_view_mode.xml b/app/src/main/res/drawable/pdf_view_mode.xml new file mode 100644 index 0000000..bad5069 --- /dev/null +++ b/app/src/main/res/drawable/pdf_view_mode.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/activity_pdf_view.xml b/app/src/main/res/layout/activity_pdf_view.xml index 9681592..9bcd387 100644 --- a/app/src/main/res/layout/activity_pdf_view.xml +++ b/app/src/main/res/layout/activity_pdf_view.xml @@ -67,10 +67,34 @@ + + + + + + + + + android:textSize="12sp" /> + android:layout_width="20dp" + android:layout_height="20dp" + android:src="@drawable/add_bookmarks" /> + android:textSize="12sp" /> diff --git a/app/src/main/res/layout/dialog_list_more.xml b/app/src/main/res/layout/dialog_list_more.xml index 5bd6b70..2f780f7 100644 --- a/app/src/main/res/layout/dialog_list_more.xml +++ b/app/src/main/res/layout/dialog_list_more.xml @@ -2,6 +2,7 @@ diff --git a/app/src/main/res/layout/dialog_permission.xml b/app/src/main/res/layout/dialog_permission.xml index d684bbe..f5a0468 100644 --- a/app/src/main/res/layout/dialog_permission.xml +++ b/app/src/main/res/layout/dialog_permission.xml @@ -3,7 +3,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/dr_rounded_corner_12_bg_white" android:orientation="vertical" android:padding="16dp" tools:ignore="UseCompoundDrawables"> diff --git a/app/src/main/res/layout/dialog_view_model.xml b/app/src/main/res/layout/dialog_view_model.xml new file mode 100644 index 0000000..9a6500e --- /dev/null +++ b/app/src/main/res/layout/dialog_view_model.xml @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 398c107..5d35676 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -96,4 +96,5 @@ Duplicate file created successfully Duplicate file created failed Processing… + View Model \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index a845da4..8a15370 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -17,4 +17,18 @@ true + + + + \ No newline at end of file