显示pdf

This commit is contained in:
ocean 2025-09-04 18:32:01 +08:00
parent 9b5cd5e014
commit daaa2e4de5
27 changed files with 329 additions and 59 deletions

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,7 +1,10 @@
import org.gradle.kotlin.dsl.implementation
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.devtools.ksp)
id("kotlin-parcelize")
}
android {
@ -54,4 +57,7 @@ dependencies {
implementation(libs.androidx.room.runtime)
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.room.ktx)
implementation(libs.glide)
implementation(libs.androidpdfviewer)
implementation(libs.pdfbox.android)
}

View File

@ -19,3 +19,5 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-keep class com.shockwave.**

View File

@ -11,7 +11,8 @@
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!-- 读取所有文件权限Android 11+ 需要特殊处理) -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application
@ -21,10 +22,10 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PDFReaderPro"
android:requestLegacyExternalStorage="true"
tools:targetApi="36">
<activity
@ -42,13 +43,20 @@
android:name=".ui.act.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.PDFReaderPro">
android:theme="@style/Theme.PDFReaderPro" />
<activity
android:name=".ui.act.PdfViewActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.PDFReaderPro">
<!-- 处理PDF文件打开 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/pdf" />
<data android:scheme="file" />
<data android:scheme="content" />

View File

@ -1,8 +1,11 @@
package com.all.pdfreader.pro.app.room.entity
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Parcelize
@Entity(tableName = "pdf_documents")
data class PdfDocumentEntity(
@PrimaryKey
@ -28,4 +31,4 @@ data class PdfDocumentEntity(
val metadataKeywords: String? = null, // PDF元数据关键词
val metadataCreationDate: Long? = null, // PDF创建时间
val metadataModificationDate: Long? = null // PDF修改时间
)
): Parcelable

View File

@ -4,11 +4,13 @@ import android.app.Activity
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.all.pdfreader.pro.app.room.repository.PdfRepository
import com.all.pdfreader.pro.app.sp.AppStore
import com.all.pdfreader.pro.app.util.StoragePermissionHelper
import com.tom_roush.pdfbox.contentstream.operator.text.ShowText
abstract class BaseActivity : AppCompatActivity() {
@ -60,6 +62,10 @@ abstract class BaseActivity : AppCompatActivity() {
Log.w("ocean", "$TAG: $message")
}
protected fun showToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
//获取数据库实例
protected fun getRepository(): PdfRepository {
return PdfRepository.getInstance()

View File

@ -0,0 +1,100 @@
package com.all.pdfreader.pro.app.ui.act
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
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.room.entity.PdfDocumentEntity
import com.github.barteksc.pdfviewer.listener.OnErrorListener
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener
import kotlinx.coroutines.launch
import java.io.File
class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeListener,
OnErrorListener {
override val TAG: String = "PdfViewActivity"
private lateinit var binding: ActivityPdfViewBinding
private lateinit var pdfDocument: PdfDocumentEntity
private val pdfRepository = getRepository()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityPdfViewBinding.inflate(layoutInflater)
setContentView(binding.root)
// 获取传递的PDF文档数据
pdfDocument = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(EXTRA_PDF_DOCUMENT, PdfDocumentEntity::class.java)
} else {
@Suppress("DEPRECATION") intent.getParcelableExtra<PdfDocumentEntity>(EXTRA_PDF_DOCUMENT)
} ?: throw IllegalArgumentException("PDF document data is required")
loadPdf()
}
private fun loadPdf() {
// 使用传递的文件路径加载PDF
val file = File(pdfDocument.filePath)
if (file.exists()) {
binding.pdfview
.fromFile(file)
.defaultPage(pdfDocument.lastReadPage) // 从上次阅读页码开始
.enableDoubletap(true)// 是否允许双击缩放
.onLoad(this)
.enableAnnotationRendering(true) // 是否渲染注释(如评论、颜色、表单等)
.onError(this)
.onPageChange(this)
.load()
} else {
showToast(getString(R.string.file_not) + ": ${pdfDocument.fileName}")
finish()
}
}
//PDF 文档加载完成时回调
override fun loadComplete(nbPages: Int) {
}
//PDF 加载出错时回调
override fun onError(t: Throwable?) {
}
//页面切换时回调
override fun onPageChanged(page: Int, pageCount: Int) {
// 保存阅读进度
pdfDocument = pdfDocument.copy(
lastReadPage = page, readingProgress = (page.toFloat() / pageCount.toFloat()) * 100
)
}
override fun onDestroy() {
super.onDestroy()
saveReadingProgress()
}
private fun saveReadingProgress() {
lifecycleScope.launch {
pdfRepository.updateReadingProgress(
pdfDocument.fileHash, pdfDocument.lastReadPage, pdfDocument.readingProgress
)
}
}
companion object {
private const val EXTRA_PDF_DOCUMENT = "extra_pdf_document"
// 创建启动Intent的便捷方法
fun createIntent(context: Context, pdfDocument: PdfDocumentEntity): Intent {
return Intent(context, PdfViewActivity::class.java).apply {
putExtra(EXTRA_PDF_DOCUMENT, pdfDocument)
}
}
}
}

View File

@ -6,8 +6,12 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.all.pdfreader.pro.app.databinding.AdapterPdfItemBinding
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.FileUtils.toFormatFileSize
import com.all.pdfreader.pro.app.util.FileUtils.toSlashDate
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
class PdfAdapter(
private var pdfList: MutableList<PdfDocumentEntity>,
@ -30,6 +34,9 @@ class PdfAdapter(
holder.binding.tvFileName.text = item.fileName
holder.binding.tvFileSize.text = item.fileSize.toFormatFileSize()
holder.binding.tvFileDate.text = item.lastModified.toSlashDate()
Glide.with(holder.binding.root).load(item.thumbnailPath)
.transform(CenterCrop(), RoundedCorners(8.dpToPx(holder.binding.root.context)))
.into(holder.binding.tvFileImg)
holder.binding.root.setOnClickListener {
onItemClick(item)

View File

@ -14,6 +14,7 @@ import com.all.pdfreader.pro.app.model.SortConfig
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.room.repository.PdfRepository
import com.all.pdfreader.pro.app.ui.act.MainActivity
import com.all.pdfreader.pro.app.ui.act.PdfViewActivity
import com.all.pdfreader.pro.app.ui.adapter.PdfAdapter
import com.all.pdfreader.pro.app.util.PdfScanner
import kotlinx.coroutines.launch
@ -37,7 +38,9 @@ class HomeFrag : BaseFrag(), MainActivity.SortableFragment {
private fun initView() {
adapter = PdfAdapter(pdfList = mutableListOf(), onItemClick = { pdf ->
Toast.makeText(requireContext(), "点击: ${pdf.fileName}", Toast.LENGTH_SHORT).show()
val intent = PdfViewActivity.createIntent(requireContext(), pdf)
startActivity(intent)
}, onMoreClick = { pdf ->
Toast.makeText(requireContext(), "更多操作: ${pdf.fileName}", Toast.LENGTH_SHORT).show()
})

View File

@ -1,5 +1,6 @@
package com.all.pdfreader.pro.app.util
import android.content.Context
import android.view.View
object AppUtils {
@ -36,4 +37,9 @@ object AppUtils {
.start()
}
}
fun Int.dpToPx(context: Context): Int {
return (this * context.resources.displayMetrics.density).toInt()
}
}

View File

@ -3,29 +3,17 @@ package com.all.pdfreader.pro.app.util
import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.provider.OpenableColumns
import android.util.Log
import android.webkit.MimeTypeMap
import androidx.annotation.RequiresApi
import java.io.File
import java.io.InputStream
import java.security.MessageDigest
import com.all.pdfreader.pro.app.util.StoragePermissionHelper
import java.text.SimpleDateFormat
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Date
import java.util.Locale
object FileUtils {
private val PDF_MIME_TYPES = setOf(
"application/pdf", "application/x-pdf"
)
fun scanPdfFiles(context: Context): List<File> {
val pdfFiles = mutableListOf<File>()

View File

@ -2,6 +2,8 @@ package com.all.pdfreader.pro.app.util
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
import android.util.Log
@ -13,6 +15,8 @@ import java.io.File
import java.io.FileOutputStream
import java.util.concurrent.TimeUnit
import androidx.core.graphics.createBitmap
import com.github.barteksc.pdfviewer.PDFView
import java.util.concurrent.CountDownLatch
class PdfScanner(
private val context: Context,
@ -32,16 +36,28 @@ class PdfScanner(
// 扫描应用私有目录(无需权限)
val privateFiles = FileUtils.scanPdfFiles(context)
LogUtil.logDebug("ocean", "PdfScanner: 📁 应用私有目录找到: ${privateFiles.size} 个PDF文件")
LogUtil.logDebug(
"ocean",
"PdfScanner: 📁 应用私有目录找到: ${privateFiles.size} 个PDF文件"
)
privateFiles.forEach { file ->
LogUtil.logDebug("ocean", "PdfScanner: 📄 ${file.name} (${FileUtils.formatFileSize(file.length())})")
LogUtil.logDebug(
"ocean",
"PdfScanner: 📄 ${file.name} (${FileUtils.formatFileSize(file.length())})"
)
}
// 扫描MediaStore需要权限
val mediaStoreFiles = FileUtils.scanPdfFilesFromMediaStore(context)
LogUtil.logDebug("ocean", "PdfScanner: 📱 MediaStore找到: ${mediaStoreFiles.size} 个PDF文件")
LogUtil.logDebug(
"ocean",
"PdfScanner: 📱 MediaStore找到: ${mediaStoreFiles.size} 个PDF文件"
)
mediaStoreFiles.forEach { file ->
LogUtil.logDebug("ocean", "PdfScanner: 📱 ${file.name} (${FileUtils.formatFileSize(file.length())})")
LogUtil.logDebug(
"ocean",
"PdfScanner: 📱 ${file.name} (${FileUtils.formatFileSize(file.length())})"
)
}
// 合并并去重
@ -50,7 +66,10 @@ class PdfScanner(
// 处理每个PDF文件
allFiles.forEachIndexed { index, file ->
LogUtil.logDebug("ocean", "PdfScanner: 🔄 处理文件 ${index + 1}/${allFiles.size}: ${file.name}")
LogUtil.logDebug(
"ocean",
"PdfScanner: 🔄 处理文件 ${index + 1}/${allFiles.size}: ${file.name}"
)
if (FileUtils.isPdfFile(file)) {
val fileHash = FileUtils.calculateFileHash(file.absolutePath)
@ -60,7 +79,10 @@ class PdfScanner(
val existingDoc = pdfRepository.getDocumentByHash(fileHash)
if (existingDoc == null) {
LogUtil.logDebug("ocean", "PdfScanner: 🆕 发现新PDF文件: ${file.name}")
LogUtil.logDebug(
"ocean",
"PdfScanner: 🆕 发现新PDF文件: ${file.name}"
)
val thumbnailPath = generateThumbnail(context, file)
val metadata =
@ -81,11 +103,20 @@ class PdfScanner(
metadataModificationDate = metadata?.modificationDate?.time
)
pdfRepository.insertOrUpdateDocument(document)
LogUtil.logDebug("ocean", "PdfScanner: ✅ 已保存到数据库: ${file.name}")
LogUtil.logDebug(
"ocean",
"PdfScanner: ✅ 已保存到数据库: ${file.name}"
)
} else {
LogUtil.logDebug("ocean", "PdfScanner: 📋 文件已存在: ${file.name}")
LogUtil.logDebug(
"ocean",
"PdfScanner: 📋 文件已存在: ${file.name}"
)
if (existingDoc.filePath != file.absolutePath) {
LogUtil.logDebug("ocean", "PdfScanner: 🔄 更新文件路径: ${existingDoc.filePath} -> ${file.absolutePath}")
LogUtil.logDebug(
"ocean",
"PdfScanner: 🔄 更新文件路径: ${existingDoc.filePath} -> ${file.absolutePath}"
)
val updatedDoc = existingDoc.copy(
filePath = file.absolutePath,
lastModified = file.lastModified()
@ -103,14 +134,21 @@ class PdfScanner(
docs.forEach { doc ->
LogUtil.logDebug(
"ocean",
"PdfScanner: 📖 ${doc.fileName} - ${doc.pageCount}页 - ${FileUtils.formatFileSize(doc.fileSize)} - ${doc.thumbnailPath}"
"PdfScanner: 📖 ${doc.fileName} - ${doc.pageCount}页 - ${
FileUtils.formatFileSize(
doc.fileSize
)
} - ${doc.thumbnailPath}"
)
}
// 标记扫描完成
ScanManager.markScanComplete(context)
val lastScanTime = ScanManager.getLastScanTime(context)
LogUtil.logDebug("ocean", "PdfScanner: ✅ 扫描完成,记录时间: ${java.util.Date(lastScanTime)}")
LogUtil.logDebug(
"ocean",
"PdfScanner: ✅ 扫描完成,记录时间: ${java.util.Date(lastScanTime)}"
)
callback.invoke(true)
}
@ -137,12 +175,17 @@ class PdfScanner(
private fun generateThumbnail(context: Context, pdfFile: File): String? {
return try {
val fileDescriptor = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
val fileDescriptor =
ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)
val pdfRenderer = PdfRenderer(fileDescriptor)
if (pdfRenderer.pageCount > 0) {
val page = pdfRenderer.openPage(0)
// 创建 Bitmap
val bitmap = createBitmap(page.width, page.height)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE) // 填充白色背景
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
page.close()
@ -169,5 +212,4 @@ class PdfScanner(
null
}
}
}

View File

@ -0,0 +1,9 @@
<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="M927.9,478.1 L168.9,478.1l308.7,-308.9c11.7,-11.7 11.4,-30.9 -0.6,-42.9 -12,-12 -31.2,-12.2 -42.9,-0.5L75.2,484.9c-2,1.7 -3.8,3.6 -5.3,5.7 -4,5.4 -6,11.8 -5.9,18.3 -0.1,7.8 2.7,15.6 8.6,21.4l361.6,361.7c11.7,11.7 30.9,11.4 42.9,-0.5 12,-12 12.2,-31.2 0.6,-42.9L168.4,539.5l759.4,0c16.5,0 29.9,-13.7 29.9,-30.7S944.4,478.1 927.9,478.1z"
android:fillColor="#2c2c2c"/>
</vector>

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">
<stroke android:color="@color/line_color"
android:width="1dp"/>
<corners android:radius="8dp" />
</shape>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -90,7 +90,7 @@
<LinearLayout
android:id="@+id/pnLayout"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_height="64dp"
android:background="@drawable/dr_rounded_corner_top_bg_grey"
android:gravity="center_vertical"
android:orientation="horizontal"
@ -115,18 +115,20 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_medium"
android:text="@string/notice"
android:textColor="@color/black"
android:textSize="16sp" />
android:textSize="14sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@font/poppins_regular"
android:maxLines="2"
android:text="@string/permission_notice"
android:textColor="@color/black_60"
android:textSize="14sp" />
android:textSize="12sp" />
</LinearLayout>
@ -140,14 +142,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/dr_click_btn_bg"
android:fontFamily="@font/poppins_semibold"
android:paddingStart="24dp"
android:paddingTop="4dp"
android:paddingEnd="24dp"
android:paddingBottom="4dp"
android:text="@string/go"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold" />
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
@ -173,6 +175,7 @@
android:id="@+id/home_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular"
android:text="@string/home"
android:textColor="@color/black"
android:textSize="14sp" />
@ -196,6 +199,7 @@
android:id="@+id/recently_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular"
android:text="@string/recently"
android:textColor="@color/black"
android:textSize="14sp" />
@ -219,6 +223,7 @@
android:id="@+id/favorite_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular"
android:text="@string/favorite"
android:textColor="@color/black"
android:textSize="14sp" />
@ -242,6 +247,7 @@
android:id="@+id/tools_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_regular"
android:text="@string/tools"
android:textColor="@color/black"
android:textSize="14sp" />

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/backBtn"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:gravity="center">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/back_black" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/bg_color">
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>

View File

@ -2,8 +2,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/bg_color"
android:gravity="center"
android:orientation="vertical">
<!-- App Logo -->
@ -19,10 +19,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:fontFamily="@font/poppins_semibold"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="28sp"
android:textStyle="bold" />
android:textSize="28sp" />
<!-- App Description -->
<TextView
@ -31,6 +31,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:alpha="0.8"
android:fontFamily="@font/poppins_medium"
android:text="@string/splash_desc"
android:textColor="@color/black"
android:textSize="16sp" />

View File

@ -14,12 +14,19 @@
android:gravity="center_vertical"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/dr_item_img_frame">
<ImageView
android:id="@+id/tvFileImg"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@mipmap/ic_launcher_round" />
</RelativeLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
@ -32,12 +39,12 @@
android:id="@+id/tvFileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/black"
android:maxLines="1"
android:ellipsize="marquee"
android:textSize="16sp"
android:textStyle="bold" />
android:fontFamily="@font/poppins_semibold"/>
<LinearLayout
android:layout_width="match_parent"
@ -51,6 +58,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2月27,2025"
android:fontFamily="@font/poppins_medium"
android:textColor="@color/black_60"
android:textSize="14sp" />
@ -60,6 +68,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="8.1MB"
android:fontFamily="@font/poppins_medium"
android:textColor="@color/black_60"
android:textSize="14sp" />

View File

@ -40,17 +40,18 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:fontFamily="@font/poppins_semibold"
android:gravity="center"
android:text="@string/permission_required"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="bold" />
android:textSize="20sp" />
<TextView
android:id="@+id/pr_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:fontFamily="@font/poppins_regular"
android:gravity="center"
android:text="@string/permission_required_desc_1"
android:textColor="@color/black_80"
@ -76,6 +77,7 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:fontFamily="@font/poppins_regular"
android:gravity="center_vertical"
android:text="@string/permission_required_desc_2"
android:textColor="@color/black_80"
@ -105,10 +107,10 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/poppins_semibold"
android:text="@string/allow_access"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -13,7 +13,7 @@
android:text="@string/sort_by"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
android:fontFamily="@font/poppins_semibold"/>
<LinearLayout
android:layout_width="match_parent"
@ -41,6 +41,7 @@
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="@string/created_date"
android:fontFamily="@font/poppins_regular"
android:textColor="@color/black"
android:textSize="16sp" />
@ -69,6 +70,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:fontFamily="@font/poppins_regular"
android:layout_weight="1"
android:text="@string/file_name"
android:textColor="@color/black"
@ -101,6 +103,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:fontFamily="@font/poppins_regular"
android:text="@string/file_size"
android:textColor="@color/black"
android:textSize="16sp" />
@ -145,6 +148,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:fontFamily="@font/poppins_regular"
android:text="@string/ascending"
android:textColor="@color/black"
android:textSize="16sp" />
@ -177,6 +181,7 @@
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="@string/descending"
android:fontFamily="@font/poppins_regular"
android:textColor="@color/black"
android:textSize="16sp" />
@ -211,7 +216,7 @@
android:text="@string/cancel"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
android:fontFamily="@font/poppins_semibold" />
</LinearLayout>
<LinearLayout
@ -229,7 +234,7 @@
android:text="@string/ok"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
android:fontFamily="@font/poppins_semibold" />
</LinearLayout>
</LinearLayout>

View File

@ -18,7 +18,9 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="40dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -21,6 +21,7 @@
<string name="file_size">File Size</string>
<string name="ascending">Ascending</string>
<string name="descending">Descending</string>
<string name="permission_denied">权限被拒绝</string>
<string name="permission_denied">Permission Denied</string>
<string name="pd_content_notice">Unable to access PDF file, please grant storage permission in settings</string>
<string name="file_not">File does not exist</string>
</resources>

View File

@ -1,6 +1,8 @@
[versions]
androidpdfviewer = "3.2.8"
appcompat = "1.7.1"
agp = "8.10.1"
glide = "5.0.4"
kotlin = "2.0.21"
ksp = "2.0.21-1.0.27"
coreKtx = "1.17.0"
@ -10,6 +12,7 @@ espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.9.2"
immersionbar = "3.2.2"
immersionbarKtx = "3.2.2"
pdfboxAndroid = "2.0.27.0"
room_version = "2.7.2"
swiperefreshlayout = "1.1.0"
recyclerview = "1.4.0"
@ -17,11 +20,13 @@ protoliteWellKnownTypes = "18.0.1"
material = "1.12.0"
[libraries]
androidpdfviewer = { module = "com.github.marain87:AndroidPdfViewer", version.ref = "androidpdfviewer" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room_version" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room_version" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room_version" }
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
@ -30,6 +35,7 @@ immersionbar = { group = "com.geyifeng.immersionbar", name = "immersionbar", ver
immersionbar-ktx = { group = "com.geyifeng.immersionbar", name = "immersionbar-ktx", version.ref = "immersionbarKtx" }
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "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" }

View File

@ -16,6 +16,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}