添加加密展示

添加密码对话框
添加输入框显示或隐藏密码。
This commit is contained in:
ocean 2025-09-08 18:24:03 +08:00
parent 687ac17419
commit ff14a8f3ee
15 changed files with 284 additions and 137 deletions

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
android:theme="@style/Theme.PDFReaderPro"
tools:ignore="DiscouragedApi,LockedOrientationActivity,RedundantLabel">
<!-- Android 11+ 存储权限 --> <!-- Android 11+ 存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@ -32,6 +34,7 @@
android:name=".ui.act.SplashActivity" android:name=".ui.act.SplashActivity"
android:exported="true" android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/Theme.PDFReaderPro"> android:theme="@style/Theme.PDFReaderPro">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -43,12 +46,13 @@
android:name=".ui.act.MainActivity" android:name=".ui.act.MainActivity"
android:exported="true" android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.PDFReaderPro" /> android:screenOrientation="portrait" />
<activity <activity
android:name=".ui.act.PdfViewActivity" android:name=".ui.act.PdfViewActivity"
android:exported="true" android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/Theme.PDFReaderPro"> android:theme="@style/Theme.PDFReaderPro">
<!-- 处理PDF文件打开 --> <!-- 处理PDF文件打开 -->
<intent-filter> <intent-filter>

View File

@ -2,6 +2,7 @@ package com.all.pdfreader.pro.app.ui.adapter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.all.pdfreader.pro.app.databinding.AdapterPdfItemBinding import com.all.pdfreader.pro.app.databinding.AdapterPdfItemBinding
@ -34,9 +35,16 @@ class PdfAdapter(
holder.binding.tvFileName.text = item.fileName holder.binding.tvFileName.text = item.fileName
holder.binding.tvFileSize.text = item.fileSize.toFormatFileSize() holder.binding.tvFileSize.text = item.fileSize.toFormatFileSize()
holder.binding.tvFileDate.text = item.lastModified.toSlashDate() holder.binding.tvFileDate.text = item.lastModified.toSlashDate()
if (item.isPassword) {
holder.binding.lockLayout.visibility = View.VISIBLE
holder.binding.tvFileImg.visibility = View.GONE
} else {
holder.binding.lockLayout.visibility = View.GONE
holder.binding.tvFileImg.visibility = View.VISIBLE
Glide.with(holder.binding.root).load(item.thumbnailPath) Glide.with(holder.binding.root).load(item.thumbnailPath)
.transform(CenterCrop(), RoundedCorners(8.dpToPx(holder.binding.root.context))) .transform(CenterCrop(), RoundedCorners(8.dpToPx(holder.binding.root.context)))
.into(holder.binding.tvFileImg) .into(holder.binding.tvFileImg)
}
holder.binding.root.setOnClickListener { holder.binding.root.setOnClickListener {
onItemClick(item) onItemClick(item)

View File

@ -1,28 +1,15 @@
package com.all.pdfreader.pro.app.ui.dialog package com.all.pdfreader.pro.app.ui.dialog
import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle import android.os.Bundle
import android.text.InputType
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import androidx.core.graphics.drawable.toDrawable
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogPdfPasswordProtectionBinding import com.all.pdfreader.pro.app.databinding.DialogPdfPasswordProtectionBinding
import com.all.pdfreader.pro.app.databinding.DialogPermissionBinding
import com.all.pdfreader.pro.app.databinding.DialogSortBinding
import com.all.pdfreader.pro.app.model.SortConfig
import com.all.pdfreader.pro.app.model.SortDirection
import com.all.pdfreader.pro.app.model.SortField
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.sp.AppStore
import com.all.pdfreader.pro.app.ui.act.MainActivity.SortableFragment
import com.all.pdfreader.pro.app.ui.view.CustomPasswordTransformation
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import androidx.core.graphics.drawable.toDrawable
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
import com.all.pdfreader.pro.app.util.FileUtils.isPdfPasswordCorrect import com.all.pdfreader.pro.app.util.FileUtils.isPdfPasswordCorrect
import java.io.File import java.io.File
@ -34,6 +21,7 @@ class PdfPasswordProtectionDialogFragment(
) : DialogFragment() { ) : DialogFragment() {
private lateinit var binding: DialogPdfPasswordProtectionBinding private lateinit var binding: DialogPdfPasswordProtectionBinding
var isPasswordVisible = false
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@ -61,22 +49,41 @@ class PdfPasswordProtectionDialogFragment(
binding.etPassword.showKeyboard() binding.etPassword.showKeyboard()
binding.tvCancel.setOnClickListener { binding.tvCancel.setOnClickListener {
onCancelClick() onCancelClick()
dismiss() dismiss()
} }
binding.tvConfirm.setOnClickListener { binding.tvConfirm.setOnClickListener {
val password = binding.etPassword.text.toString() val password = binding.etPassword.text.toString()
if(password.isEmpty()){ if (password.isEmpty()) {
binding.tilPassword.error = getString(R.string.password_not_empty) binding.tilPassword.error = getString(R.string.password_not_empty)
return@setOnClickListener return@setOnClickListener
} }
if(isPdfPasswordCorrect(requireActivity(),file,password)){ if (isPdfPasswordCorrect(requireActivity(), file, password)) {
onOkClick(password) onOkClick(password)
dismiss() dismiss()
}else{ } else {
binding.tilPassword.error = getString(R.string.incorrect_password) binding.tilPassword.error = getString(R.string.incorrect_password)
} }
} }
binding.showPasswordBtn.setOnClickListener {
isPasswordVisible = !isPasswordVisible
showOrHidePassword(isPasswordVisible)
}
}
private fun showOrHidePassword(b: Boolean) {
if (b) {
binding.etPassword.inputType =
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
binding.showPasswordIv.setImageResource(R.drawable.show_password)
} else {
binding.etPassword.inputType =
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
binding.showPasswordIv.setImageResource(R.drawable.hide_password)
}
// 保持光标在末尾
binding.etPassword.setSelection(binding.etPassword.text?.length ?: 0)
} }
} }

View File

@ -1,63 +1,88 @@
package com.all.pdfreader.pro.app.ui.dialog package com.all.pdfreader.pro.app.ui.dialog
import android.content.Context import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.InputType
import android.text.TextWatcher import android.text.TextWatcher
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogPdfSetPasswordBinding import com.all.pdfreader.pro.app.databinding.DialogPdfSetPasswordBinding
import com.all.pdfreader.pro.app.util.AppUtils.showKeyboard
import com.google.android.material.textfield.TextInputEditText
class PdfSetPasswordDialog : DialogFragment() { class PdfSetPasswordDialog(
private val onCancelled: () -> Unit, private val onPasswordSet: (String) -> Unit
) : DialogFragment(
private var _binding: DialogPdfSetPasswordBinding? = null ) {
private val binding get() = _binding!! private lateinit var binding: DialogPdfSetPasswordBinding
private var listener: PasswordDialogListener? = null private var isEnterPasswordVisible = false
private var isConfirmPasswordVisible = false
interface PasswordDialogListener {
fun onPasswordSet(password: String?)
fun onPasswordDialogCancelled()
}
companion object {
fun newInstance(): PdfSetPasswordDialog {
return PdfSetPasswordDialog()
}
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
container: ViewGroup?,
savedInstanceState: Bundle?
): View? { ): View? {
_binding = DialogPdfSetPasswordBinding.inflate(inflater, container, false) binding = DialogPdfSetPasswordBinding.inflate(layoutInflater)
return binding.root return binding.root
} }
override fun onStart() {
super.onStart()
isCancelable = false
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?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.etPassword.showKeyboard()
setupListeners() setupListeners()
setupTextWatchers() setupTextWatchers()
} }
private fun setupListeners() { private fun setupListeners() {
binding.tvCancel.setOnClickListener { binding.tvCancel.setOnClickListener {
listener?.onPasswordDialogCancelled() onCancelled()
dismiss() dismiss()
} }
binding.tvConfirm.setOnClickListener { binding.tvConfirm.setOnClickListener {
val password = binding.etPassword.text.toString() val password = binding.etPassword.text.toString()
val confirmPassword = binding.etConfirmPassword.text.toString() val confirmPassword = binding.etConfirmPassword.text.toString()
if (validatePassword(password, confirmPassword)) { if (validatePassword(password, confirmPassword)) {
listener?.onPasswordSet(password) onPasswordSet(password)
dismiss() dismiss()
} }
} }
binding.enterShowPasswordBtn.setOnClickListener {
isEnterPasswordVisible = !isEnterPasswordVisible
showOrHidePassword(
binding.etPassword,
binding.enterShowPasswordIv,
isEnterPasswordVisible
)
}
binding.confirmShowPasswordBtn.setOnClickListener {
isConfirmPasswordVisible = !isConfirmPasswordVisible
showOrHidePassword(
binding.etConfirmPassword,
binding.confirmShowPasswordIv,
isConfirmPasswordVisible
)
}
} }
private fun setupTextWatchers() { private fun setupTextWatchers() {
@ -86,7 +111,7 @@ class PdfSetPasswordDialog : DialogFragment() {
binding.tilConfirmPassword.error = null binding.tilConfirmPassword.error = null
if (password.isNotEmpty() && confirmPassword.isNotEmpty() && password != confirmPassword) { if (password.isNotEmpty() && confirmPassword.isNotEmpty() && password != confirmPassword) {
binding.tilConfirmPassword.error = "密码不匹配" binding.tilConfirmPassword.error = getString(R.string.password_not_match)
} }
} }
@ -94,42 +119,38 @@ class PdfSetPasswordDialog : DialogFragment() {
binding.tilPassword.error = null binding.tilPassword.error = null
binding.tilConfirmPassword.error = null binding.tilConfirmPassword.error = null
// 允许空密码(表示不设置密码) // 允许空密码
if (password.isEmpty()) { if (password.isEmpty()) {
return true binding.tilPassword.error = getString(R.string.password_not_empty)
return false
} }
// 密码长度验证 // 密码长度验证
if (password.length < 4) { if (password.length < 4) {
binding.tilPassword.error = "密码长度至少为4位" binding.tilPassword.error = getString(R.string.password_too_short)
return false return false
} }
// 密码匹配验证 // 密码匹配验证
if (password != confirmPassword) { if (password != confirmPassword) {
binding.tilConfirmPassword.error = "密码不匹配" binding.tilConfirmPassword.error = getString(R.string.password_not_match)
return false return false
} }
return true return true
} }
override fun onAttach(context: Context) { private fun showOrHidePassword(inputView: TextInputEditText, imageView: ImageView, b: Boolean) {
super.onAttach(context) if (b) {
if (context is PasswordDialogListener) { inputView.inputType =
listener = context InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
imageView.setImageResource(R.drawable.show_password)
} else { } else {
throw RuntimeException("$context must implement PasswordDialogListener") inputView.inputType =
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
imageView.setImageResource(R.drawable.hide_password)
} }
} // 保持光标在末尾
inputView.setSelection(inputView.text?.length ?: 0)
override fun onDetach() {
super.onDetach()
listener = null
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
} }
} }

View File

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
@ -40,9 +39,8 @@ class HomeFrag : BaseFrag(), MainActivity.SortableFragment {
adapter = PdfAdapter(pdfList = mutableListOf(), onItemClick = { pdf -> adapter = PdfAdapter(pdfList = mutableListOf(), onItemClick = { pdf ->
val intent = PdfViewActivity.createIntent(requireContext(), pdf.filePath) val intent = PdfViewActivity.createIntent(requireContext(), pdf.filePath)
startActivity(intent) startActivity(intent)
}, onMoreClick = { pdf -> }, onMoreClick = { pdf ->
Toast.makeText(requireContext(), "更多操作: ${pdf.fileName}", Toast.LENGTH_SHORT).show()
}) })
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext()) binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())

View File

@ -1,24 +0,0 @@
package com.all.pdfreader.pro.app.ui.view
import android.text.method.PasswordTransformationMethod
import android.view.View
class CustomPasswordTransformation : PasswordTransformationMethod() {
override fun getTransformation(source: CharSequence, view: View): CharSequence {
return PasswordCharSequence(source)
}
private class PasswordCharSequence(private val mSource: CharSequence) : CharSequence {
override val length: Int
get() = mSource.length
override fun get(index: Int): Char {
// 最后一位显示原字符,其余显示●
return if (index == mSource.length - 1) mSource[index] else '●'
}
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
return mSource.subSequence(startIndex, endIndex)
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp"/>
<solid android:color="@color/grey"/>
</shape>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="366.8dp"
android:height="256dp"
android:viewportWidth="1467"
android:viewportHeight="1024">
<path
android:pathData="M299.1,18.5l917.2,917.2a34.1,34.1 0,0 1,-48.3 48.3L250.9,66.7A34.1,34.1 0,1 1,299.1 18.5zM324.6,188.7l50.6,50.6a918.1,918.1 0,0 0,-113.9 67.5,829.3 829.3,0 0,0 -93.1,75.2l-14.1,13.6c-4.5,4.5 -8.9,8.9 -13.1,13.3l-12,12.9A438.3,438.3 0,0 0,99.7 457.4l-7.3,10.6c-10,15.2 -15.5,27.6 -15.9,35.9 -0.6,15.4 23.2,51.4 64.1,93.3l12.7,12.8c28.7,27.9 64.2,57.8 104.4,85.5 140.2,96.5 308.7,155.6 475.9,155.6 75.1,0 150,-11 222.1,-31.2l54.7,54.7c-85.3,27.7 -178.8,44.7 -276.8,44.7 -256.6,0 -483.8,-126.3 -612.9,-246l-13.2,-12.6c-12.9,-12.6 -24.6,-25 -35.2,-37.1l-10.1,-12a468.4,468.4 0,0 1,-4.8 -5.9l-8.9,-11.7C21.6,557.3 7.3,524.7 8.3,501.2c0.9,-21.5 13.8,-50.7 37,-83.5l8.6,-11.7 9.5,-12 5.1,-6.1 10.7,-12.4 5.6,-6.2 11.9,-12.6 12.6,-12.8c4.4,-4.3 8.8,-8.6 13.4,-12.9l14.1,-12.9c12.1,-10.8 24.9,-21.6 38.4,-32.3l16.6,-12.8a976.1,976.1 0,0 1,132.7 -84.2zM733.6,83c400.6,0 725.3,284.8 725.3,418.1 0,42.4 -32.9,100.2 -90.6,159.2l-12.8,12.7 -6.7,6.3 -13.9,12.7c-4.7,4.2 -9.6,8.4 -14.6,12.6l-15.3,12.6c-5.2,4.2 -10.5,8.3 -16,12.5l-16.6,12.4a929.4,929.4 0,0 1,-125.5 76.1l-51,-50.9a880.5,880.5 0,0 0,112.4 -63.8c58.2,-39 106.9,-82.3 140.3,-123.6 28.1,-34.7 41.9,-64.1 41.9,-78.7 0,-14.6 -13.8,-44 -41.8,-78.7 -33.4,-41.3 -82.1,-84.7 -140.3,-123.6 -136.9,-91.6 -305.5,-147.6 -474.9,-147.6 -74.3,0 -148.5,11.7 -220.2,33.2l-54.1,-54.2c84.4,-29.1 177,-47.2 274.4,-47.2zM536.7,400.8l52,52a152.7,152.7 0,0 0,193.2 193.2l52,52.1a220.9,220.9 0,0 1,-297.2 -297.3zM733.6,280.2a220.9,220.9 0,0 1,196.9 321.3L878.5,549.5a152.7,152.7 0,0 0,-193.2 -193.2L633.2,304.3a220,220 0,0 1,100.4 -24.1z"
android:fillColor="#bfbfbf"/>
</vector>

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="M785.1,416h-61.9v-121.6c0,-108.8 -91.7,-198.4 -202.7,-198.4s-202.7,89.6 -202.7,198.4v121.6h-78.9c-55.5,0 -100.3,44.8 -100.3,100.3v311.5c0,55.5 44.8,100.3 100.3,100.3h546.1c55.5,0 100.3,-44.8 100.3,-100.3L885.3,516.3c0,-55.5 -44.8,-100.3 -100.3,-100.3zM381.9,294.4c0,-74.7 61.9,-134.4 138.7,-134.4s138.7,59.7 138.7,134.4v121.6h-277.3v-121.6zM821.3,827.7c0,19.2 -17.1,36.3 -36.3,36.3L238.9,864c-19.2,0 -36.3,-17.1 -36.3,-36.3L202.7,516.3c0,-19.2 17.1,-36.3 36.3,-36.3h546.1c19.2,0 36.3,17.1 36.3,36.3v311.5z"
android:fillColor="#666666"/>
<path
android:pathData="M512,544c-17.1,0 -32,14.9 -32,32v106.7c0,17.1 14.9,32 32,32s32,-14.9 32,-32v-106.7c0,-17.1 -14.9,-32 -32,-32z"
android:fillColor="#666666"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="433dp"
android:height="256dp"
android:viewportWidth="1732"
android:viewportHeight="1024">
<path
android:pathData="M872.8,34.5c462.2,0 836.9,328.7 836.9,482.5 0,49 -37.9,115.6 -104.5,183.7l-14.7,14.6 -7.7,7.3 -16,14.6c-5.5,4.9 -11.1,9.7 -16.8,14.6l-17.6,14.5c-6,4.8 -12.2,9.6 -18.4,14.4l-19.2,14.3c-153.2,110.8 -375.1,204.5 -622,204.5 -296,0 -558.2,-145.7 -707.2,-283.9l-15.3,-14.5c-14.8,-14.5 -28.4,-28.8 -40.6,-42.8l-11.7,-13.9a540.4,540.4 0,0 1,-5.5 -6.9l-10.3,-13.5C51.2,581.7 34.8,544.1 35.8,516.9c1,-24.9 16,-58.4 42.7,-96.4l10,-13.5 10.9,-13.9c1.9,-2.4 3.8,-4.7 5.8,-7.1l12.3,-14.3 6.5,-7.2 13.7,-14.6 14.6,-14.7c5,-4.9 10.2,-9.9 15.5,-14.8l16.3,-14.9c13.9,-12.4 28.8,-24.9 44.3,-37.3l19.1,-14.8c152.8,-115.4 375.5,-219.1 625.2,-219.1zM872.8,113.2c-192.4,0 -384.2,67.9 -544.9,179.4a957,957 0,0 0,-107.4 86.7l-16.3,15.6c-5.2,5.2 -10.3,10.3 -15.1,15.4l-13.9,14.9a505.7,505.7 0,0 0,-33.8 41.2l-8.4,12.2c-11.5,17.6 -18,31.9 -18.4,41.5 -0.7,17.7 26.9,59.2 74,107.6l14.7,14.7c33.1,32.2 74,66.6 120.5,98.6 161.8,111.3 356.2,179.6 549.1,179.6 195.5,0 390.1,-64.5 548,-170.2 67.2,-45 123.4,-95 161.9,-142.7 32.3,-40 48.3,-74 48.3,-90.8 0,-16.8 -16,-50.7 -48.2,-90.8 -38.5,-47.7 -94.7,-97.7 -161.9,-142.7 -157.9,-105.7 -352.5,-170.3 -548,-170.3zM872.8,262a254.9,254.9 0,1 1,0 509.9,254.9 254.9,0 0,1 0,-509.9zM872.8,340.8a176.2,176.2 0,1 0,0 352.4,176.2 176.2,0 0,0 0,-352.4z"
android:fillColor="#bfbfbf"/>
</vector>

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="M785.1,416L381.9,416v-121.6c0,-74.7 61.9,-134.4 138.7,-134.4 59.7,0 113.1,36.3 132.3,91.7 6.4,17.1 23.5,25.6 40.5,19.2 17.1,-6.4 25.6,-23.5 19.2,-40.5 -27.7,-81.1 -104.5,-134.4 -192,-134.4 -110.9,0 -202.7,89.6 -202.7,198.4v121.6h-78.9c-55.5,0 -100.3,44.8 -100.3,100.3v311.5c0,55.5 44.8,100.3 100.3,100.3h546.1c55.5,0 100.3,-44.8 100.3,-100.3L885.3,516.3c0,-55.5 -44.8,-100.3 -100.3,-100.3zM821.3,827.7c0,19.2 -17.1,36.3 -36.3,36.3L238.9,864c-19.2,0 -36.3,-17.1 -36.3,-36.3L202.7,516.3c0,-19.2 17.1,-36.3 36.3,-36.3h546.1c19.2,0 36.3,17.1 36.3,36.3v311.5z"
android:fillColor="#666666"/>
<path
android:pathData="M512,544c-17.1,0 -32,14.9 -32,32v106.7c0,17.1 14.9,32 32,32s32,-14.9 32,-32v-106.7c0,-17.1 -14.9,-32 -32,-32z"
android:fillColor="#666666"/>
</vector>

View File

@ -25,6 +25,20 @@
android:layout_height="56dp" android:layout_height="56dp"
android:src="@mipmap/ic_launcher_round" /> android:src="@mipmap/ic_launcher_round" />
<LinearLayout
android:visibility="gone"
android:id="@+id/lock_layout"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/dr_item_lock_bg"
android:gravity="center">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/lock" />
</LinearLayout>
</RelativeLayout> </RelativeLayout>
<LinearLayout <LinearLayout
@ -40,11 +54,11 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="middle" android:ellipsize="middle"
android:fontFamily="@font/poppins_semibold"
android:maxLines="1" android:maxLines="1"
android:text="@string/app_name" android:text="@string/app_name"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="16sp" android:textSize="16sp" />
android:fontFamily="@font/poppins_semibold"/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -57,8 +71,8 @@
android:id="@+id/tvFileDate" android:id="@+id/tvFileDate"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="2月27,2025"
android:fontFamily="@font/poppins_medium" android:fontFamily="@font/poppins_medium"
android:text="2月27,2025"
android:textColor="@color/black_60" android:textColor="@color/black_60"
android:textSize="14sp" /> android:textSize="14sp" />
@ -67,8 +81,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:text="8.1MB"
android:fontFamily="@font/poppins_medium" android:fontFamily="@font/poppins_medium"
android:text="8.1MB"
android:textColor="@color/black_60" android:textColor="@color/black_60"
android:textSize="14sp" /> android:textSize="14sp" />

View File

@ -27,11 +27,15 @@
android:textColor="@color/black_80" android:textColor="@color/black_80"
android:textSize="14sp" /> android:textSize="14sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilPassword" android:id="@+id/tilPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="@string/enter_password" android:hint="@string/enter_password"
app:endIconMode="password_toggle" app:endIconMode="password_toggle"
app:passwordToggleEnabled="true"> app:passwordToggleEnabled="true">
@ -39,13 +43,31 @@
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/etPassword" android:id="@+id/etPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:textSize="16sp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular" android:fontFamily="@font/poppins_regular"
android:inputType="textPassword" /> android:inputType="textPassword"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/showPasswordBtn"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignEnd="@id/tilPassword"
android:layout_centerVertical="true"
android:gravity="center">
<ImageView
android:id="@+id/showPasswordIv"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/hide_password" />
</LinearLayout>
</RelativeLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -27,11 +27,15 @@
android:textColor="@color/black_60" android:textColor="@color/black_60"
android:textSize="14sp" /> android:textSize="14sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilPassword" android:id="@+id/tilPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="@string/enter_password" android:hint="@string/enter_password"
app:endIconMode="password_toggle" app:endIconMode="password_toggle"
app:passwordToggleEnabled="true"> app:passwordToggleEnabled="true">
@ -42,15 +46,37 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular" android:fontFamily="@font/poppins_regular"
android:inputType="textPassword" android:inputType="textPassword"
android:textSize="14sp" /> android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/enterShowPasswordBtn"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignEnd="@id/tilPassword"
android:layout_centerVertical="true"
android:gravity="center">
<ImageView
android:id="@+id/enterShowPasswordIv"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/hide_password" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilConfirmPassword" android:id="@+id/tilConfirmPassword"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:hint="@string/confirm_password" android:hint="@string/confirm_password"
app:endIconMode="password_toggle" app:endIconMode="password_toggle"
app:passwordToggleEnabled="true"> app:passwordToggleEnabled="true">
@ -61,10 +87,28 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular" android:fontFamily="@font/poppins_regular"
android:inputType="textPassword" android:inputType="textPassword"
android:textSize="14sp" /> android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/confirmShowPasswordBtn"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignEnd="@id/tilConfirmPassword"
android:layout_centerVertical="true"
android:gravity="center">
<ImageView
android:id="@+id/confirmShowPasswordIv"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/hide_password" />
</LinearLayout>
</RelativeLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -79,7 +123,8 @@
android:fontFamily="@font/poppins_regular" android:fontFamily="@font/poppins_regular"
android:padding="12dp" android:padding="12dp"
android:text="@string/cancel" android:text="@string/cancel"
android:textColor="@color/black_80" /> android:textColor="@color/black_80"
android:textSize="16sp" />
<TextView <TextView
android:id="@+id/tvConfirm" android:id="@+id/tvConfirm"
@ -88,7 +133,8 @@
android:fontFamily="@font/poppins_medium" android:fontFamily="@font/poppins_medium"
android:padding="12dp" android:padding="12dp"
android:text="@string/ok" android:text="@string/ok"
android:textColor="@color/black" /> android:textColor="@color/black"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>

View File

@ -29,7 +29,7 @@
<string name="eye_protect">Eye Protect</string> <string name="eye_protect">Eye Protect</string>
<string name="bookmarks">Bookmarks</string> <string name="bookmarks">Bookmarks</string>
<string name="set_pdf_password">Set PDF Password</string> <string name="set_pdf_password">Set PDF Password</string>
<string name="set_pdf_password_dialog_desc">Set a protection password for the PDF file,Leaving it blank means no password is set.</string> <string name="set_pdf_password_dialog_desc">Set a protection password for the PDF file, Leaving it blank means no password is set.</string>
<string name="password_protection">PDF Password Protection</string> <string name="password_protection">PDF Password Protection</string>
<string name="enter_password">Enter password</string> <string name="enter_password">Enter password</string>
<string name="confirm_password">Confirm password</string> <string name="confirm_password">Confirm password</string>
@ -37,4 +37,6 @@
<string name="password_not_empty">Password cannot be empty</string> <string name="password_not_empty">Password cannot be empty</string>
<string name="incorrect_password">Incorrect password</string> <string name="incorrect_password">Incorrect password</string>
<string name="pdf_loading_failed">PDF loading failed</string> <string name="pdf_loading_failed">PDF loading failed</string>
<string name="password_too_short">Password must be at least 4 characters</string>
<string name="password_not_match">Passwords do not match</string>
</resources> </resources>