一:添加阅读模式对话框
1.水平与垂直阅读 2.逐页 3.反转颜色(夜晚模式) 二:优化fileActionEvent事件通知写法,需要观察什么事件自己写 三:添加自定义CustomSwitchButton按钮
This commit is contained in:
parent
18190d15af
commit
038c1bc46b
@ -1,5 +1,7 @@
|
||||
package com.all.pdfreader.pro.app.model
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import java.io.File
|
||||
|
||||
sealed class FileActionEvent {
|
||||
@ -16,4 +18,19 @@ sealed class FileActionEvent {
|
||||
data class RemovePassword(val status: Status, val success: Boolean? = null) : FileActionEvent() {
|
||||
enum class Status { START, COMPLETE }
|
||||
}
|
||||
|
||||
//只做通知,不携带任何数据,使用object。
|
||||
object NoticeReload : FileActionEvent()
|
||||
|
||||
inline fun <reified T : FileActionEvent> LiveData<FileActionEvent>.observeEvent(
|
||||
owner: LifecycleOwner,
|
||||
crossinline handler: (T) -> Unit
|
||||
) {
|
||||
this.observe(owner) { event ->
|
||||
if (event is T) {
|
||||
handler(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,14 +20,33 @@ class AppStore(context: Context) {
|
||||
key = DOCUMENT_SORT_TYPE, defaultValue = SortConfig.default().toPreferenceString()
|
||||
)
|
||||
|
||||
// 是否开启护眼遮罩
|
||||
var isEyeCareMode: Boolean by store.boolean(
|
||||
key = IS_EYE_CARE_MODE, defaultValue = false
|
||||
)
|
||||
|
||||
// 横or竖
|
||||
var isVertical: Boolean by store.boolean(
|
||||
key = IS_VERTICAL, defaultValue = true//默认竖
|
||||
)
|
||||
|
||||
// 是否逐页
|
||||
var isPageFling: Boolean by store.boolean(
|
||||
key = IS_PAGE_FLING, defaultValue = false
|
||||
)
|
||||
|
||||
// 是否反转颜色
|
||||
var isColorInversion: Boolean by store.boolean(
|
||||
key = IS_COLOR_INVERSION, defaultValue = false
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val FILE_NAME = "prp_sp_name"
|
||||
private const val PERMISSIONS_DIALOG_PROMPT = "permissions_dialog_prompt"
|
||||
private const val DOCUMENT_SORT_TYPE = "document_sort_type"
|
||||
private const val IS_EYE_CARE_MODE = "is_eye_care_mode"
|
||||
private const val IS_VERTICAL = "is_vertical"
|
||||
private const val IS_PAGE_FLING = "is_page_fling"
|
||||
private const val IS_COLOR_INVERSION = "is_color_inversion"
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,7 @@ import com.all.pdfreader.pro.app.util.AppUtils.setClickWithAnimation
|
||||
import com.all.pdfreader.pro.app.util.PdfScanner
|
||||
import com.all.pdfreader.pro.app.util.StoragePermissionHelper
|
||||
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
||||
import com.all.pdfreader.pro.app.viewmodel.observeEvent
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@ -71,75 +72,66 @@ class MainActivity : BaseActivity(), PermissionDialogFragment.PermissionCallback
|
||||
|
||||
private fun initObserve() {
|
||||
//观察其余操作
|
||||
viewModel.fileActionEvent.observe(this) { event ->
|
||||
when (event) {
|
||||
is FileActionEvent.Rename -> {
|
||||
if (event.renameResult.success) {
|
||||
showToast(getString(R.string.rename_successfully))
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.Rename>(this) { event ->
|
||||
if (event.renameResult.success) {
|
||||
showToast(getString(R.string.rename_successfully))
|
||||
} else {
|
||||
showToast(event.renameResult.errorMessage.toString())
|
||||
}
|
||||
}
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.Delete>(this){ event ->
|
||||
if (event.deleteResult.success) {
|
||||
showToast(getString(R.string.delete_successfully))
|
||||
} else {
|
||||
showToast(event.deleteResult.errorMessage.toString())
|
||||
}
|
||||
}
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.Favorite>(this){ event ->
|
||||
if (event.isFavorite) {
|
||||
showToast(getString(R.string.added_to_favorites))
|
||||
} else {
|
||||
showToast(getString(R.string.removed_from_favorites))
|
||||
}
|
||||
}
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.Duplicate>(this){ event ->
|
||||
if (event.file != null) {
|
||||
showToast(getString(R.string.duplicate_created_successfully))
|
||||
} else {
|
||||
showToast(getString(R.string.duplicate_created_failed))
|
||||
}
|
||||
}
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.SetPassword>(this){ event ->
|
||||
when (event.status) {
|
||||
FileActionEvent.SetPassword.Status.START -> {
|
||||
progressDialog = ProgressDialogFragment()
|
||||
progressDialog?.show(supportFragmentManager, "progressDialog")
|
||||
}
|
||||
|
||||
FileActionEvent.SetPassword.Status.COMPLETE -> {
|
||||
progressDialog?.dismiss()
|
||||
progressDialog = null
|
||||
if (event.success == true) {
|
||||
showToast(getString(R.string.set_password_successfully))
|
||||
} else {
|
||||
showToast(event.renameResult.errorMessage.toString())
|
||||
showToast(getString(R.string.set_password_failed))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.RemovePassword>(this){ event ->
|
||||
when (event.status) {
|
||||
FileActionEvent.RemovePassword.Status.START -> {
|
||||
progressDialog = ProgressDialogFragment()
|
||||
progressDialog?.show(supportFragmentManager, "progressDialog")
|
||||
}
|
||||
|
||||
is FileActionEvent.Delete -> {
|
||||
if (event.deleteResult.success) {
|
||||
showToast(getString(R.string.delete_successfully))
|
||||
FileActionEvent.RemovePassword.Status.COMPLETE -> {
|
||||
progressDialog?.dismiss()
|
||||
progressDialog = null
|
||||
if (event.success == true) {
|
||||
showToast(getString(R.string.remove_password_successfully))
|
||||
} else {
|
||||
showToast(event.deleteResult.errorMessage.toString())
|
||||
}
|
||||
}
|
||||
|
||||
is FileActionEvent.Favorite -> {
|
||||
if (event.isFavorite) {
|
||||
showToast(getString(R.string.added_to_favorites))
|
||||
} else {
|
||||
showToast(getString(R.string.removed_from_favorites))
|
||||
}
|
||||
}
|
||||
|
||||
is FileActionEvent.Duplicate -> {
|
||||
if (event.file != null) {
|
||||
showToast(getString(R.string.duplicate_created_successfully))
|
||||
} else {
|
||||
showToast(getString(R.string.duplicate_created_failed))
|
||||
}
|
||||
}
|
||||
|
||||
is FileActionEvent.SetPassword -> {
|
||||
when (event.status) {
|
||||
FileActionEvent.SetPassword.Status.START -> {
|
||||
progressDialog = ProgressDialogFragment()
|
||||
progressDialog?.show(supportFragmentManager, "progressDialog")
|
||||
}
|
||||
|
||||
FileActionEvent.SetPassword.Status.COMPLETE -> {
|
||||
progressDialog?.dismiss()
|
||||
progressDialog = null
|
||||
if (event.success == true) {
|
||||
showToast(getString(R.string.set_password_successfully))
|
||||
} else {
|
||||
showToast(getString(R.string.set_password_failed))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is FileActionEvent.RemovePassword -> {
|
||||
when (event.status) {
|
||||
FileActionEvent.RemovePassword.Status.START -> {
|
||||
progressDialog = ProgressDialogFragment()
|
||||
progressDialog?.show(supportFragmentManager, "progressDialog")
|
||||
}
|
||||
|
||||
FileActionEvent.RemovePassword.Status.COMPLETE -> {
|
||||
progressDialog?.dismiss()
|
||||
progressDialog = null
|
||||
if (event.success == true) {
|
||||
showToast(getString(R.string.remove_password_successfully))
|
||||
} else {
|
||||
showToast(getString(R.string.remove_password_failed))
|
||||
}
|
||||
}
|
||||
showToast(getString(R.string.remove_password_failed))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,10 +9,14 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.all.pdfreader.pro.app.R
|
||||
import com.all.pdfreader.pro.app.databinding.ActivityPdfViewBinding
|
||||
import com.all.pdfreader.pro.app.model.FileActionEvent
|
||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||
import com.all.pdfreader.pro.app.ui.dialog.PdfPasswordProtectionDialogFragment
|
||||
import com.all.pdfreader.pro.app.ui.dialog.ViewModelDialogFragment
|
||||
import com.all.pdfreader.pro.app.ui.view.CustomScrollHandle
|
||||
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
|
||||
import com.all.pdfreader.pro.app.viewmodel.observeEvent
|
||||
import com.github.barteksc.pdfviewer.PDFView
|
||||
import com.github.barteksc.pdfviewer.listener.OnErrorListener
|
||||
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener
|
||||
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener
|
||||
@ -69,6 +73,12 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.fileActionEvent.observeEvent<FileActionEvent.NoticeReload>(this) {
|
||||
logDebug("observeEvent NoticeReload")
|
||||
val file = File(pdfDocument.filePath)
|
||||
loadPdfInternal(file, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupOnClick() {
|
||||
@ -80,7 +90,9 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
||||
toggleEyeCareMode(appStore.isEyeCareMode)
|
||||
}
|
||||
binding.viewModelBtn.setOnClickListener {
|
||||
|
||||
ViewModelDialogFragment(pdfDocument.filePath).show(
|
||||
supportFragmentManager, "ViewModelDialogFragment"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +114,8 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
||||
|
||||
//PDF 文档加载完成时回调
|
||||
override fun loadComplete(nbPages: Int) {
|
||||
|
||||
//加载完毕进行一次缩放
|
||||
binding.pdfview.resetZoomWithAnimation()
|
||||
}
|
||||
|
||||
//PDF 加载出错时回调
|
||||
@ -161,20 +174,27 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
|
||||
}
|
||||
|
||||
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)//逐页滑动
|
||||
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)) // 自定义的页数展示
|
||||
if (appStore.isPageFling) {
|
||||
pageSnap(true)//页面可在逐页中,可居中展示,非逐页模式,滑动停止后可自动定格在居中位置。
|
||||
autoSpacing(true)//开启逐页就开启自动间距
|
||||
pageFling(true)//逐页
|
||||
} else {
|
||||
spacing(10)
|
||||
pageFling(false)
|
||||
}
|
||||
.load()
|
||||
swipeHorizontal(!appStore.isVertical)
|
||||
nightMode(appStore.isColorInversion)
|
||||
}.load()
|
||||
}
|
||||
|
||||
private fun toggleFullScreen() {
|
||||
|
||||
@ -1,36 +1,32 @@
|
||||
package com.all.pdfreader.pro.app.ui.dialog
|
||||
|
||||
import android.net.Uri
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
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.sp.AppStore
|
||||
import com.all.pdfreader.pro.app.ui.view.CustomSwitchButton
|
||||
import com.all.pdfreader.pro.app.ui.view.CustomSwitchButton.OnCheckedChangeListener
|
||||
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 val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel
|
||||
private lateinit var pdfDocument: PdfDocumentEntity
|
||||
private var isFavorite: Boolean = false
|
||||
private var isFirstSetSelected = true// 第一次直接设置位置,不做指示器的切换动画
|
||||
private val appstore by lazy { AppStore(requireActivity()) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -59,127 +55,109 @@ class ViewModelDialogFragment(val filePath: String) : BottomSheetDialogFragment(
|
||||
|
||||
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.pdfDocument.value?.let {
|
||||
pdfDocument = it
|
||||
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)
|
||||
// 初始化指示器宽度
|
||||
binding.indicator.post {
|
||||
val indicatorWidth = binding.btnHorizontal.width
|
||||
binding.indicator.layoutParams.width = indicatorWidth
|
||||
binding.indicator.requestLayout()
|
||||
setSelectedMode(appstore.isVertical)
|
||||
}
|
||||
updateCollectUi(isFavorite)
|
||||
updatePasswordUi(pdfDocument.isPassword)
|
||||
binding.switchPageByPage.setChecked(appstore.isPageFling)
|
||||
binding.switchColorInversion.setChecked(appstore.isColorInversion)
|
||||
}
|
||||
|
||||
private fun setupOnClick() {
|
||||
binding.collectBtn.setClickWithAnimation(duration = 250) {
|
||||
isFavorite = !isFavorite
|
||||
updateCollectUi(isFavorite)
|
||||
viewModel.saveCollectState(pdfDocument.filePath, isFavorite)
|
||||
dismiss()
|
||||
binding.btnHorizontal.setOnClickListener {
|
||||
setSelectedMode(isVertical = false)
|
||||
AppStore(requireActivity()).isVertical = false
|
||||
viewModel.noticeReloadPdf()
|
||||
}
|
||||
binding.renameFileBtn.setOnClickListener {
|
||||
RenameDialogFragment().show(parentFragmentManager, "ListMoreDialogFragment")
|
||||
dismiss()
|
||||
binding.btnVertical.setOnClickListener {
|
||||
setSelectedMode(isVertical = true)
|
||||
AppStore(requireActivity()).isVertical = true
|
||||
viewModel.noticeReloadPdf()
|
||||
}
|
||||
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 -> {
|
||||
|
||||
}
|
||||
binding.switchPageByPage.setOnCheckedChangeListener(object : OnCheckedChangeListener {
|
||||
override fun onCheckedChanged(view: CustomSwitchButton?, isChecked: Boolean) {
|
||||
view?.setChecked(isChecked)
|
||||
appstore.isPageFling = isChecked
|
||||
viewModel.noticeReloadPdf()
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
binding.duplicateFileBtn.setOnClickListener {
|
||||
viewModel.duplicateFile(requireActivity(), pdfDocument.filePath)
|
||||
dismiss()
|
||||
}
|
||||
binding.setPasswordBtn.setOnClickListener {
|
||||
if (pdfDocument.isPassword) {
|
||||
PdfRemovePasswordDialog().show(parentFragmentManager, "PdfRemovePasswordDialog")
|
||||
})
|
||||
binding.switchColorInversion.setOnCheckedChangeListener(object : OnCheckedChangeListener {
|
||||
override fun onCheckedChanged(
|
||||
view: CustomSwitchButton?,
|
||||
isChecked: Boolean
|
||||
) {
|
||||
view?.setChecked(isChecked)
|
||||
appstore.isColorInversion = isChecked
|
||||
viewModel.noticeReloadPdf()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setSelectedMode(isVertical: Boolean) {
|
||||
binding.apply {
|
||||
val targetX = if (isVertical) btnVertical.x else btnHorizontal.x
|
||||
|
||||
if (isFirstSetSelected) {
|
||||
indicator.translationX = targetX
|
||||
isFirstSetSelected = false
|
||||
} else {
|
||||
PdfSetPasswordDialog().show(parentFragmentManager, "PdfSetPasswordDialog")
|
||||
indicator.animate().translationX(targetX).setDuration(250)
|
||||
.setInterpolator(AccelerateDecelerateInterpolator()).start()
|
||||
}
|
||||
dismiss()
|
||||
|
||||
// 横向
|
||||
animateIconAndTextColor(
|
||||
horizontalTv,
|
||||
horizontalIv,
|
||||
if (isVertical) requireContext().getColor(R.color.white)
|
||||
else requireContext().getColor(R.color.icon_color),
|
||||
if (isVertical) requireContext().getColor(R.color.icon_color)
|
||||
else requireContext().getColor(R.color.white)
|
||||
)
|
||||
// 垂直
|
||||
animateIconAndTextColor(
|
||||
verticalTv,
|
||||
verticalIv,
|
||||
if (isVertical) requireContext().getColor(R.color.icon_color)
|
||||
else requireContext().getColor(R.color.white),
|
||||
if (isVertical) requireContext().getColor(R.color.white)
|
||||
else requireContext().getColor(R.color.icon_color)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCollectUi(b: Boolean) {
|
||||
if (b) {
|
||||
binding.collectIv.setImageResource(R.drawable.collected)
|
||||
} else {
|
||||
binding.collectIv.setImageResource(R.drawable.collect)
|
||||
|
||||
/**
|
||||
* 改变img与text的颜色值,动画渐变同步indicator的时间
|
||||
*/
|
||||
private fun animateIconAndTextColor(
|
||||
textView: TextView, imageView: ImageView, fromColor: Int, toColor: Int
|
||||
) {
|
||||
ValueAnimator.ofArgb(fromColor, toColor).apply {
|
||||
duration = 250
|
||||
addUpdateListener { animator ->
|
||||
val animatedColor = animator.animatedValue as Int
|
||||
textView.setTextColor(animatedColor)
|
||||
imageView.setColorFilter(animatedColor, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,25 +1,18 @@
|
||||
package com.all.pdfreader.pro.app.util
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.util.Log
|
||||
import androidx.core.graphics.createBitmap
|
||||
import com.all.pdfreader.pro.app.PRApp
|
||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||
import com.all.pdfreader.pro.app.util.AppUtils.generateFastThumbnail
|
||||
import com.all.pdfreader.pro.app.util.FileUtils.isPdfEncrypted
|
||||
import com.shockwave.pdfium.PdfDocument
|
||||
import com.shockwave.pdfium.PdfiumCore
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PdfScanner(
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package com.all.pdfreader.pro.app.viewmodel
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.all.pdfreader.pro.app.model.FileActionEvent
|
||||
|
||||
/**
|
||||
* 公用观察FileActionEvent事件函数,只观察需要观察的响应
|
||||
*/
|
||||
inline fun <reified T : FileActionEvent> LiveData<FileActionEvent>.observeEvent(
|
||||
owner: LifecycleOwner,
|
||||
crossinline handler: (T) -> Unit
|
||||
) {
|
||||
this.observe(owner) { event ->
|
||||
if (event is T) {
|
||||
handler(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.all.pdfreader.pro.app.PRApp
|
||||
import com.all.pdfreader.pro.app.model.FileActionEvent
|
||||
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
|
||||
import com.all.pdfreader.pro.app.room.repository.PdfRepository
|
||||
@ -156,19 +157,40 @@ class PdfViewModel : ViewModel() {
|
||||
viewModelScope.launch {
|
||||
_fileActionEvent.postValue(FileActionEvent.RemovePassword(FileActionEvent.RemovePassword.Status.START))
|
||||
|
||||
val success = withContext(Dispatchers.IO) {
|
||||
PdfSecurityUtils.removePasswordFromPdf(filePath, password).also {
|
||||
if (it) {
|
||||
val success = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val removed = PdfSecurityUtils.removePasswordFromPdf(filePath, password)
|
||||
Log.d("ocean", "密码移除$removed")
|
||||
if (removed) {
|
||||
pdfRepository.updateIsPassword(filePath, false)
|
||||
val document = pdfRepository.getDocumentByPath(filePath)
|
||||
if (document?.thumbnailPath.isNullOrEmpty()) {
|
||||
val newThumbnail = generateFastThumbnail(PRApp.getContext(), File(filePath))
|
||||
Log.d("ocean", "最新图片:$newThumbnail")
|
||||
if (!newThumbnail.isNullOrEmpty() && filePath != newThumbnail) {
|
||||
pdfRepository.updateThumbnailPath(filePath, newThumbnail)
|
||||
}
|
||||
}
|
||||
}
|
||||
removed // 这里直接返回移除密码的结果
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("ocean", "removePassword 失败", e)
|
||||
false
|
||||
}
|
||||
|
||||
_fileActionEvent.postValue(
|
||||
FileActionEvent.SetPassword(
|
||||
FileActionEvent.SetPassword.Status.COMPLETE,
|
||||
FileActionEvent.RemovePassword(
|
||||
FileActionEvent.RemovePassword.Status.COMPLETE,
|
||||
success
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun noticeReloadPdf() {
|
||||
viewModelScope.launch {
|
||||
_fileActionEvent.postValue(FileActionEvent.NoticeReload)
|
||||
}
|
||||
}
|
||||
}
|
||||
6
app/src/main/res/color/switch_thumb_color.xml
Normal file
6
app/src/main/res/color/switch_thumb_color.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 滑块颜色 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="#C8E6C9" android:state_checked="true"/> <!-- 开 -->
|
||||
<item android:color="#E0E0E0" android:state_checked="false"/> <!-- 关 -->
|
||||
</selector>
|
||||
6
app/src/main/res/color/switch_track_color.xml
Normal file
6
app/src/main/res/color/switch_track_color.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 轨道颜色 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="#4CAF50" android:state_checked="true"/> <!-- 开 -->
|
||||
<item android:color="#9E9E9E" android:state_checked="false"/> <!-- 关 -->
|
||||
</selector>
|
||||
20
app/src/main/res/drawable/color_inversion.xml
Normal file
20
app/src/main/res/drawable/color_inversion.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dip"
|
||||
android:height="24.0dip"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillAlpha="0.01"
|
||||
android:fillColor="@color/icon_color"
|
||||
android:pathData="M0,0h24v24h-24z"
|
||||
android:strokeAlpha="0.01" />
|
||||
<path
|
||||
android:fillColor="@color/icon_color"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M2,12C2,6.477 6.477,2 12,2C17.523,2 22,6.477 22,12C22,17.523 17.523,22 12,22C6.477,22 2,17.523 2,12ZM20,12C20,7.582 16.418,4 12,4C7.582,4 4,7.582 4,12C4,16.418 7.582,20 12,20C16.418,20 20,16.418 20,12Z" />
|
||||
<path
|
||||
android:fillColor="@color/icon_color"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M12,18C15.314,18 18,15.314 18,12C18,8.686 15.314,6 12,6V18Z" />
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/dr_bg_toggle_group.xml
Normal file
5
app/src/main/res/drawable/dr_bg_toggle_group.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/grey"/>
|
||||
<corners android:radius="24dp"/>
|
||||
</shape>
|
||||
5
app/src/main/res/drawable/dr_bg_toggle_indicator.xml
Normal file
5
app/src/main/res/drawable/dr_bg_toggle_indicator.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/black"/>
|
||||
<corners android:radius="24dp"/>
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="24dp"/>
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#000000"/>
|
||||
<corners android:radius="24dp"/>
|
||||
</shape>
|
||||
20
app/src/main/res/drawable/page_by_page.xml
Normal file
20
app/src/main/res/drawable/page_by_page.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M5.5,4L18.5,4C18.7761,4 19,4.2239 19,4.5L19,15.7929C19,15.9255 18.9473,16.0527 18.8536,16.1464L15.1464,19.8536C15.0527,19.9473 14.9255,20 14.7929,20L5.5,20C5.2239,20 5,19.7761 5,19.5L5,4.5C5,4.2239 5.2239,4 5.5,4Z"
|
||||
android:strokeWidth="2.0"
|
||||
android:strokeColor="@color/icon_color" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M18,15L14.5,15C14.2239,15 14,15.2239 14,15.5L14,20L14,20"
|
||||
android:strokeWidth="2.0"
|
||||
android:strokeColor="@color/icon_color"
|
||||
android:strokeLineCap="square" />
|
||||
</vector>
|
||||
13
app/src/main/res/drawable/read_horizontal.xml
Normal file
13
app/src/main/res/drawable/read_horizontal.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4,7h16v10h-16z"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="@color/icon_color"
|
||||
android:fillColor="@android:color/transparent"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeLineCap="round" />
|
||||
</vector>
|
||||
13
app/src/main/res/drawable/read_vertical.xml
Normal file
13
app/src/main/res/drawable/read_vertical.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M7,4h10v16h-10z"
|
||||
android:strokeWidth="2"
|
||||
android:strokeColor="@color/icon_color"
|
||||
android:fillColor="@android:color/transparent"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeLineCap="round" />
|
||||
</vector>
|
||||
@ -44,12 +44,13 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@color/white">
|
||||
android:gravity="center">
|
||||
|
||||
<com.github.barteksc.pdfviewer.PDFView
|
||||
android:id="@+id/pdfview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/grey" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@ -246,7 +246,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:text="@string/duplicate_file"
|
||||
android:textColor="@color/grey_text_color"
|
||||
android:textSize="16sp" />
|
||||
@ -270,7 +269,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:text="@string/set_password"
|
||||
android:textColor="@color/grey_text_color"
|
||||
android:textSize="16sp" />
|
||||
@ -292,7 +290,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:fontFamily="@font/poppins_medium"
|
||||
android:text="@string/delete_file"
|
||||
android:textColor="@color/grey_text_color"
|
||||
android:textSize="16sp" />
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<?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:orientation="vertical"
|
||||
@ -17,4 +18,161 @@
|
||||
android:background="@drawable/dr_dialog_indicator_bg" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:fontFamily="@font/poppins_semibold"
|
||||
android:text="@string/view_model"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/toggleContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@drawable/dr_bg_toggle_group"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<View
|
||||
android:id="@+id/indicator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:background="@drawable/dr_bg_toggle_indicator"
|
||||
android:translationX="0dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/horizontalIv"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/read_horizontal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/horizontalTv"
|
||||
style="@style/TextViewFont_PopMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/horizontal"
|
||||
android:textColor="@color/icon_color"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/btnVertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/verticalIv"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/read_vertical" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/verticalTv"
|
||||
style="@style/TextViewFont_PopMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/vertical"
|
||||
android:textColor="@color/icon_color"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/page_by_page" />
|
||||
|
||||
<TextView
|
||||
style="@style/TextViewFont_PopMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/page_by_page"
|
||||
android:textColor="@color/icon_color"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.all.pdfreader.pro.app.ui.view.CustomSwitchButton
|
||||
android:id="@+id/switchPageByPage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:sb_background="@color/grey"
|
||||
app:sb_show_indicator="false" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/color_inversion" />
|
||||
|
||||
<TextView
|
||||
style="@style/TextViewFont_PopMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/color_inversion"
|
||||
android:textColor="@color/icon_color"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<com.all.pdfreader.pro.app.ui.view.CustomSwitchButton
|
||||
android:id="@+id/switchColorInversion"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:sb_background="@color/grey"
|
||||
app:sb_show_indicator="false" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@ -15,4 +15,5 @@
|
||||
<color name="black_img_color">#2c2c2c</color>
|
||||
<color name="grey_text_color">#666666</color>
|
||||
<color name="eye_protection_color">#80FFD699</color>
|
||||
<color name="icon_color">#636366</color>
|
||||
</resources>
|
||||
@ -97,4 +97,8 @@
|
||||
<string name="duplicate_created_failed">Duplicate file created failed</string>
|
||||
<string name="processing">Processing…</string>
|
||||
<string name="view_model">View Model</string>
|
||||
<string name="page_by_page">Page by page</string>
|
||||
<string name="color_inversion">color inversion</string>
|
||||
<string name="horizontal">Horizontal</string>
|
||||
<string name="vertical">Vertical</string>
|
||||
</resources>
|
||||
@ -17,7 +17,7 @@
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
</style>
|
||||
|
||||
<style name="CustomBottomSheetDialogTheme" parent="@style/Theme.Design.BottomSheetDialog">
|
||||
<style name="CustomBottomSheetDialogTheme" parent="@style/Theme.MaterialComponents.Light.BottomSheetDialog">
|
||||
<!-- 关键属性:取消浮动效果 -->
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
<!-- 设置导航栏颜色 -->
|
||||
@ -31,4 +31,18 @@
|
||||
<item name="android:background">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="TextViewFont_PopMedium">
|
||||
<item name="android:includeFontPadding">false</item>
|
||||
<item name="android:fontFamily">@font/poppins_medium</item>
|
||||
</style>
|
||||
|
||||
<style name="TextViewFont_PopRegular">
|
||||
<item name="android:includeFontPadding">false</item>
|
||||
<item name="android:fontFamily">@font/poppins_regular</item>
|
||||
</style>
|
||||
|
||||
<style name="TextViewFont_PopSemiBold">
|
||||
<item name="android:includeFontPadding">false</item>
|
||||
<item name="android:fontFamily">@font/poppins_semibold</item>
|
||||
</style>
|
||||
</resources>
|
||||
30
app/src/main/res/values/switch_button_attrs.xml
Normal file
30
app/src/main/res/values/switch_button_attrs.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="SwitchButton">
|
||||
|
||||
<attr name="sb_shadow_radius" format="reference|dimension"/>
|
||||
<attr name="sb_shadow_offset" format="reference|dimension"/>
|
||||
<attr name="sb_shadow_color" format="reference|color"/>
|
||||
<attr name="sb_uncheck_color" format="reference|color"/>
|
||||
<attr name="sb_checked_color" format="reference|color"/>
|
||||
|
||||
<attr name="sb_border_width" format="reference|dimension"/>
|
||||
<attr name="sb_checkline_color" format="reference|color"/>
|
||||
<attr name="sb_checkline_width" format="reference|dimension"/>
|
||||
<attr name="sb_uncheckcircle_color" format="reference|color"/>
|
||||
<attr name="sb_uncheckcircle_width" format="reference|dimension"/>
|
||||
<attr name="sb_uncheckcircle_radius" format="reference|dimension"/>
|
||||
|
||||
<attr name="sb_checked" format="reference|boolean"/>
|
||||
<attr name="sb_shadow_effect" format="reference|boolean"/>
|
||||
<attr name="sb_effect_duration" format="reference|integer"/>
|
||||
<attr name="sb_button_color" format="reference|color"/>
|
||||
<attr name="sb_show_indicator" format="reference|boolean"/>
|
||||
<attr name="sb_background" format="reference|color"/>
|
||||
<attr name="sb_enable_effect" format="reference|boolean"/>
|
||||
|
||||
<attr name="sb_checkedbutton_color" format="reference|color"/>
|
||||
<attr name="sb_uncheckbutton_color" format="reference|color"/>
|
||||
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@ -19,6 +19,7 @@ swiperefreshlayout = "1.1.0"
|
||||
recyclerview = "1.4.0"
|
||||
protoliteWellKnownTypes = "18.0.1"
|
||||
material = "1.12.0"
|
||||
composeMaterial3 = "1.5.1"
|
||||
|
||||
[libraries]
|
||||
androidpdfviewer = { module = "com.github.marain87:AndroidPdfViewer", version.ref = "androidpdfviewer" }
|
||||
@ -40,6 +41,7 @@ androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview"
|
||||
pdfbox-android = { module = "com.tom-roush:pdfbox-android", version.ref = "pdfboxAndroid" }
|
||||
protolite-well-known-types = { group = "com.google.firebase", name = "protolite-well-known-types", version.ref = "protoliteWellKnownTypes" }
|
||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||
androidx-compose-material3 = { group = "androidx.wear.compose", name = "compose-material3", version.ref = "composeMaterial3" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user