1.添加书签功能(添加与删除)

2.优化阅读界面滚动标签在横模式下的淡出淡入
This commit is contained in:
ocean 2025-09-17 18:40:36 +08:00
parent e03830a6a6
commit 5fea68bd95
34 changed files with 791 additions and 133 deletions

View File

@ -1,7 +1,5 @@
package com.all.pdfreader.pro.app.model package com.all.pdfreader.pro.app.model
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import java.io.File import java.io.File
sealed class FileActionEvent { sealed class FileActionEvent {
@ -15,22 +13,15 @@ sealed class FileActionEvent {
enum class Status { START, COMPLETE } enum class Status { START, COMPLETE }
} }
data class RemovePassword(val status: Status, val success: Boolean? = null) : FileActionEvent() { data class RemovePassword(val status: Status, val success: Boolean? = null) :
FileActionEvent() {
enum class Status { START, COMPLETE } enum class Status { START, COMPLETE }
} }
//只做通知不携带任何数据使用object。 //只做通知不携带任何数据使用object。
object NoticeReload : FileActionEvent() object NoticeReload : FileActionEvent()
inline fun <reified T : FileActionEvent> LiveData<FileActionEvent>.observeEvent( data class AddBookmark(val success: Boolean) : FileActionEvent()
owner: LifecycleOwner, data class DeleteBookmark(val success: Boolean) : FileActionEvent()
crossinline handler: (T) -> Unit data class DeleteAllBookmark(val success: Boolean) : FileActionEvent()
) {
this.observe(owner) { event ->
if (event is T) {
handler(event)
}
}
}
} }

View File

@ -11,10 +11,10 @@ interface BookmarkDao {
suspend fun insert(bookmark: BookmarkEntity): Long suspend fun insert(bookmark: BookmarkEntity): Long
@Update @Update
suspend fun update(bookmark: BookmarkEntity) suspend fun update(bookmark: BookmarkEntity): Int
@Delete @Delete
suspend fun delete(bookmark: BookmarkEntity) suspend fun delete(bookmark: BookmarkEntity): Int
@Query("SELECT * FROM bookmarks WHERE id = :bookmarkId") @Query("SELECT * FROM bookmarks WHERE id = :bookmarkId")
suspend fun getById(bookmarkId: Long): BookmarkEntity? suspend fun getById(bookmarkId: Long): BookmarkEntity?
@ -29,7 +29,7 @@ interface BookmarkDao {
suspend fun getBookmarkCount(filePath: String): Int suspend fun getBookmarkCount(filePath: String): Int
@Query("DELETE FROM bookmarks WHERE filePath = :filePath") @Query("DELETE FROM bookmarks WHERE filePath = :filePath")
suspend fun deleteAllByPdf(filePath: String) suspend fun deleteAllByPdf(filePath: String): Int
@Query("DELETE FROM bookmarks WHERE filePath = :filePath AND pageNumber = :pageNumber") @Query("DELETE FROM bookmarks WHERE filePath = :filePath AND pageNumber = :pageNumber")
suspend fun deleteByPage(filePath: String, pageNumber: Int) suspend fun deleteByPage(filePath: String, pageNumber: Int)

View File

@ -39,12 +39,16 @@ class PdfRepository private constructor(context: Context) {
fun searchDocuments(query: String): Flow<List<PdfDocumentEntity>> = fun searchDocuments(query: String): Flow<List<PdfDocumentEntity>> =
pdfDao.searchDocuments(query) pdfDao.searchDocuments(query)
suspend fun updateFilePathAndFileName(oldFilePath: String, newFilePath: String, newName: String) { suspend fun updateFilePathAndFileName(
oldFilePath: String,
newFilePath: String,
newName: String
) {
pdfDao.updateFilePathAndFileName(oldFilePath, newFilePath, newName) pdfDao.updateFilePathAndFileName(oldFilePath, newFilePath, newName)
} }
//语句更新可响应flow //语句更新可响应flow
suspend fun updateIsPassword(filePath: String, hasPassword: Boolean){ suspend fun updateIsPassword(filePath: String, hasPassword: Boolean) {
pdfDao.updateIsPassword(filePath, hasPassword) pdfDao.updateIsPassword(filePath, hasPassword)
} }
@ -105,8 +109,12 @@ class PdfRepository private constructor(context: Context) {
// 书签相关操作 // 书签相关操作
suspend fun addBookmark(bookmark: BookmarkEntity): Long = bookmarkDao.insert(bookmark) suspend fun addBookmark(bookmark: BookmarkEntity): Long = bookmarkDao.insert(bookmark)
suspend fun updateBookmark(bookmark: BookmarkEntity) = bookmarkDao.update(bookmark) suspend fun updateBookmark(bookmark: BookmarkEntity): Int = bookmarkDao.update(bookmark)
suspend fun deleteBookmark(bookmark: BookmarkEntity) = bookmarkDao.delete(bookmark) suspend fun deleteBookmark(bookmark: BookmarkEntity): Int = bookmarkDao.delete(bookmark)
suspend fun deleteAllBookmark(filePath: String): Int {
return bookmarkDao.deleteAllByPdf(filePath)
}
fun getBookmarksByPdf(filePath: String): Flow<List<BookmarkEntity>> = fun getBookmarksByPdf(filePath: String): Flow<List<BookmarkEntity>> =
bookmarkDao.getBookmarksByPdf(filePath) bookmarkDao.getBookmarksByPdf(filePath)

View File

@ -3,20 +3,22 @@ package com.all.pdfreader.pro.app.ui.act
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import androidx.core.os.HandlerCompat.postDelayed
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.ActivityPdfViewBinding import com.all.pdfreader.pro.app.databinding.ActivityPdfViewBinding
import com.all.pdfreader.pro.app.model.FileActionEvent import com.all.pdfreader.pro.app.model.FileActionEvent
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.ui.dialog.BookmarksDialogFragment
import com.all.pdfreader.pro.app.ui.dialog.PdfPasswordProtectionDialogFragment 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.dialog.ViewModelDialogFragment
import com.all.pdfreader.pro.app.ui.view.CustomScrollHandle import com.all.pdfreader.pro.app.ui.view.CustomScrollHandle
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
import com.all.pdfreader.pro.app.viewmodel.observeEvent 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.OnErrorListener
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener import com.github.barteksc.pdfviewer.listener.OnPageChangeListener
@ -58,6 +60,8 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
?: throw IllegalArgumentException("PDF file hash is required") ?: throw IllegalArgumentException("PDF file hash is required")
// 加载PDF数据 // 加载PDF数据
viewModel.getPDFDocument(filePath) viewModel.getPDFDocument(filePath)
//加载书签数据
viewModel.getBookmarks(filePath)
} }
private fun initObserve() { private fun initObserve() {
@ -73,12 +77,34 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
finish() finish()
} }
} }
//观察书签数据
viewModel.pdfBookmark.observe(this) { list ->
logDebug("observe->bookmarks: ${list.size}")
list?.let {
binding.bookmarksHint.text = "${it.size}"
if (it.isEmpty()) {
binding.bookmarksHint.visibility = View.GONE
} else {
binding.bookmarksHint.visibility = View.VISIBLE
}
} ?: run {
binding.bookmarksHint.visibility = View.GONE
}
}
viewModel.fileActionEvent.observeEvent<FileActionEvent.NoticeReload>(this) { viewModel.fileActionEvent.observeEvent<FileActionEvent.NoticeReload>(this) {
logDebug("observeEvent NoticeReload") logDebug("observeEvent NoticeReload")
val file = File(pdfDocument.filePath) val file = File(pdfDocument.filePath)
loadPdfInternal(file, null) loadPdfInternal(file, null)
} }
viewModel.fileActionEvent.observeEvent<FileActionEvent.AddBookmark>(this) {
if (it.success) {
showToast(getString(R.string.bookmark_add_success))
} else {
showToast(getString(R.string.bookmark_add_fail))
}
}
} }
private fun setupOnClick() { private fun setupOnClick() {
@ -90,12 +116,15 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
toggleEyeCareMode(appStore.isEyeCareMode) toggleEyeCareMode(appStore.isEyeCareMode)
} }
binding.viewModelBtn.setOnClickListener { binding.viewModelBtn.setOnClickListener {
ViewModelDialogFragment(pdfDocument.filePath).show( ViewModelDialogFragment().show(supportFragmentManager, "ViewModelDialogFragment")
supportFragmentManager, "ViewModelDialogFragment"
)
} }
binding.bookmarksBtn.setOnClickListener { binding.bookmarksBtn.setOnClickListener {
BookmarksDialogFragment(pdfDocument, onJumpPage = {
binding.pdfview.jumpTo(it)
binding.pdfview.postDelayed({
binding.pdfview.resetZoomWithAnimation()
}, 200)
}).show(supportFragmentManager, "BookmarksDialogFragment")
} }
} }

View File

@ -0,0 +1,66 @@
package com.all.pdfreader.pro.app.ui.adapter
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.all.pdfreader.pro.app.databinding.AdapterItemBookmarkPageBinding
import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
class BookmarkAdapter(
private var list: MutableList<BookmarkEntity>,
private val onItemClick: (BookmarkEntity) -> Unit,
private val onEditClick: (BookmarkEntity) -> Unit,
private val onDeleteClick: (BookmarkEntity, Int) -> Unit,
) : RecyclerView.Adapter<BookmarkAdapter.PdfViewHolder>() {
inner class PdfViewHolder(val binding: AdapterItemBookmarkPageBinding) :
RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PdfViewHolder {
val binding = AdapterItemBookmarkPageBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return PdfViewHolder(binding)
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: PdfViewHolder, position: Int) {
val item = list[position]
holder.binding.titleTv.text = item.label
holder.binding.descTv.text = "(#${item.pageNumber + 1})"
holder.binding.root.setOnClickListener {
onItemClick(item)
}
holder.binding.editBtn.setOnClickListener {
onEditClick(item)
}
holder.binding.deleteBtn.setOnClickListener {
onDeleteClick(item, position)
}
}
override fun getItemCount(): Int = list.size
@SuppressLint("NotifyDataSetChanged")
fun updateData(newList: List<BookmarkEntity>) {
list.clear()
list.addAll(newList)
notifyDataSetChanged()
}
fun removeItem(position: Int) {
list.removeAt(position)
notifyItemRemoved(position)
}
fun removeAllItems() {
val size = list.size
if (size > 0) {
list.clear()
notifyItemRangeRemoved(0, size)
}
}
}

View File

@ -1,32 +1,31 @@
package com.all.pdfreader.pro.app.ui.dialog package com.all.pdfreader.pro.app.ui.dialog
import android.animation.ValueAnimator
import android.graphics.PorterDuff
import android.os.Bundle import android.os.Bundle
import android.util.Log
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.animation.AccelerateDecelerateInterpolator
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogBookmarksBinding import com.all.pdfreader.pro.app.databinding.DialogBookmarksBinding
import com.all.pdfreader.pro.app.databinding.DialogViewModelBinding import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.sp.AppStore import com.all.pdfreader.pro.app.ui.adapter.BookmarkAdapter
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.all.pdfreader.pro.app.viewmodel.PdfViewModel
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class BookmarksDialogFragment(val filePath: String) : BottomSheetDialogFragment() { class BookmarksDialogFragment(
private val pdfDocument: PdfDocumentEntity,
private val onJumpPage: (Int) -> Unit
) :
BottomSheetDialogFragment() {
private lateinit var binding: DialogBookmarksBinding private lateinit var binding: DialogBookmarksBinding
private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel
private lateinit var pdfDocument: PdfDocumentEntity private lateinit var bookmarks: List<BookmarkEntity>
private val appstore by lazy { AppStore(requireActivity()) } private lateinit var adapter: BookmarkAdapter
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -55,21 +54,97 @@ class BookmarksDialogFragment(val filePath: String) : BottomSheetDialogFragment(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.pdfDocument.value?.let { if (pdfDocument.filePath.isEmpty()) {
pdfDocument = it
initUi()
setupOnClick()
} ?: run {
showToast(getString(R.string.file_not)) showToast(getString(R.string.file_not))
dismiss() dismiss()
} }
//观察书签数据
viewModel.pdfBookmark.observe(this) { list ->
Log.d("ocean","BookmarksDialogFragment observe")
list?.let {
bookmarks = it
initView()
setupOnClick()
}
}
viewModel.getBookmarks(pdfDocument.filePath)
} }
private fun initUi() { private fun initView() {
adapter = BookmarkAdapter(list = mutableListOf(), onItemClick = { bookmark ->
onJumpPage(bookmark.pageNumber)
dismiss()
}, onEditClick = { bookmark ->
}, onDeleteClick = { bookmark, position ->
adapter.removeItem(position)
bookmarks = bookmarks.filter { it.id != bookmark.id }
viewModel.deleteBookMark(bookmark)
})
binding.bookmarksPageRv.layoutManager = LinearLayoutManager(requireContext())
binding.bookmarksPageRv.adapter = adapter
if (bookmarks.isEmpty()) {
binding.noBookmarksPageLayout.visibility = View.VISIBLE//显示没有书签的提示布局
binding.bookmarksDisplayLayout.visibility = View.GONE//隐藏显示内容的布局
binding.addBtn.visibility = View.GONE//隐藏顶部的add按钮因为布局noBookmarksPageLayout里面也会有一个add按钮
} else {
binding.noBookmarksPageLayout.visibility = View.GONE
binding.bookmarksDisplayLayout.visibility = View.VISIBLE
binding.addBtn.visibility = View.VISIBLE
// 检查当前页是否已存在书签
val alreadyBookmarked = bookmarks.any { it.pageNumber == pdfDocument.lastReadPage }
binding.addBtn.isEnabled = !alreadyBookmarked
if (alreadyBookmarked) {
binding.addTv.text = getString(R.string.added)
binding.addTv.setTextColor(requireActivity().getColor(R.color.grey_text_color))
binding.addBtn.setBackgroundResource(R.drawable.dr_btn_not_clickable_bg)
binding.addIv.setImageResource(R.drawable.bookmark_icon_red)
} else {
binding.addTv.text = getString(R.string.add)
binding.addTv.setTextColor(requireActivity().getColor(R.color.white))
binding.addBtn.setBackgroundResource(R.drawable.dr_click_btn_red_bg)
binding.addIv.setImageResource(R.drawable.add_icon_white)
}
updateAdapter()
}
} }
private fun setupOnClick() { private fun setupOnClick() {
binding.addBookmarkBtn.setOnClickListener {
dialogAddBookMarks()
}
binding.addBtn.setOnClickListener {
dialogAddBookMarks()
}
binding.deleteALLPageBtn.setOnClickListener {
DeleteDialogFragment(
getString(R.string.delete_bookmarks_title),
getString(R.string.delete_bookmarks_desc),
onDeleteClick = {
viewModel.deleteAllBookmark(pdfDocument.filePath)
adapter.removeAllItems()
bookmarks = emptyList()
}).show(parentFragmentManager, "DeleteDialogFragment")
}
}
private fun dialogAddBookMarks() {
val bookmark = BookmarkEntity(
filePath = pdfDocument.filePath,
pageNumber = pdfDocument.lastReadPage,
label = getString(R.string.page) + "${pdfDocument.lastReadPage + 1}"
)
viewModel.addBookMark(bookmark)
dismiss()
}
private fun updateAdapter() {
if (bookmarks.isNotEmpty()) {
val sortedBookmarks = bookmarks.sortedByDescending { it.createTime }
adapter.updateData(sortedBookmarks)
}
} }
private fun showToast(message: String) { private fun showToast(message: String) {

View File

@ -8,17 +8,16 @@ import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import com.all.pdfreader.pro.app.R import com.all.pdfreader.pro.app.R
import com.all.pdfreader.pro.app.databinding.DialogDeleteBinding import com.all.pdfreader.pro.app.databinding.DialogDeleteBinding
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
class DeleteDialogFragment() : DialogFragment() { class DeleteDialogFragment(
private val title: String,
private val desc: String,
private val onDeleteClick: () -> Unit
) : DialogFragment() {
private lateinit var binding: DialogDeleteBinding private lateinit var binding: DialogDeleteBinding
private val viewModel: PdfViewModel by activityViewModels()
private lateinit var pdfDocument: PdfDocumentEntity
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
@ -42,18 +41,14 @@ class DeleteDialogFragment() : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel.pdfDocument.value?.let { binding.deleteTitleTv.text = title
pdfDocument = it binding.deleteDescTv.text = desc
setupOnClick() setupOnClick()
} ?: run {
showToast(getString(R.string.file_not))
dismiss()
}
} }
private fun setupOnClick() { private fun setupOnClick() {
binding.okBtn.setOnClickListener { binding.okBtn.setOnClickListener {
viewModel.deleteFile(pdfDocument.filePath) onDeleteClick()
dismiss() dismiss()
} }
binding.cancelBtn.setOnClickListener { binding.cancelBtn.setOnClickListener {

View File

@ -99,7 +99,12 @@ class ListMoreDialogFragment(val filePath: String) : BottomSheetDialogFragment()
dismiss() dismiss()
} }
binding.deleteFileBtn.setOnClickListener { binding.deleteFileBtn.setOnClickListener {
DeleteDialogFragment().show(parentFragmentManager, "DeleteDialogFragment") DeleteDialogFragment(
getString(R.string.delete_file_title),
getString(R.string.delete_file_desc),
onDeleteClick = {
viewModel.deleteFile(pdfDocument.filePath)
}).show(parentFragmentManager, "DeleteDialogFragment")
dismiss() dismiss()
} }
binding.detailsBtn.setOnClickListener { binding.detailsBtn.setOnClickListener {

View File

@ -20,7 +20,7 @@ import com.all.pdfreader.pro.app.ui.view.CustomSwitchButton.OnCheckedChangeListe
import com.all.pdfreader.pro.app.viewmodel.PdfViewModel import com.all.pdfreader.pro.app.viewmodel.PdfViewModel
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class ViewModelDialogFragment(val filePath: String) : BottomSheetDialogFragment() { class ViewModelDialogFragment() : BottomSheetDialogFragment() {
private lateinit var binding: DialogViewModelBinding private lateinit var binding: DialogViewModelBinding
private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel private val viewModel: PdfViewModel by activityViewModels()//为PdfViewActivity的PdfViewModel

View File

@ -18,8 +18,10 @@ import com.github.barteksc.pdfviewer.scroll.ScrollHandle;
import com.github.barteksc.pdfviewer.util.Util; import com.github.barteksc.pdfviewer.util.Util;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
/**
* 重写了DefaultScrollHandle代码添加动画效果自定义background
*/
public class CustomScrollHandle extends RelativeLayout implements ScrollHandle { public class CustomScrollHandle extends RelativeLayout implements ScrollHandle {
private final static int HANDLE_LONG = 36; private final static int HANDLE_LONG = 36;
private final static int HANDLE_SHORT = 28; private final static int HANDLE_SHORT = 28;
@ -173,24 +175,28 @@ public class CustomScrollHandle extends RelativeLayout implements ScrollHandle {
@Override @Override
public void show() { public void show() {
if (getVisibility() != VISIBLE) { if (getVisibility() != VISIBLE) {
setTranslationX(getWidth()); // 初始在右侧外面
setAlpha(0f); setAlpha(0f);
if (pdfView.isSwipeVertical()) {
setTranslationX(getWidth()); // 初始在右侧外面
animate().translationX(0).alpha(1f).setDuration(450).start();
} else {
setTranslationY(getHeight()); // 初始在底部外面
animate().translationY(0).alpha(1f).setDuration(450).start();
}
setVisibility(VISIBLE); setVisibility(VISIBLE);
animate().translationX(0)
.alpha(1f)
.setDuration(450)
.start();
} }
} }
@Override @Override
public void hide() { public void hide() {
if (getVisibility() == VISIBLE) { if (getVisibility() == VISIBLE) {
if (pdfView.isSwipeVertical()) {
animate().translationX(getWidth()) // 滑到右边外面 animate().translationX(getWidth()) // 滑到右边外面
.alpha(0f) .alpha(0f).setDuration(450).withEndAction(() -> setVisibility(INVISIBLE)).start();
.setDuration(450) } else {
.withEndAction(() -> setVisibility(INVISIBLE)) animate().translationY(getHeight()) // 滑到下边外面
.start(); .alpha(0f).setDuration(450).withEndAction(() -> setVisibility(INVISIBLE)).start();
}
} }
} }
@ -208,7 +214,7 @@ public class CustomScrollHandle extends RelativeLayout implements ScrollHandle {
/** /**
* @param tf 自定义font字体 * @param tf 自定义font字体
*/ */
public void setTypeface(Typeface tf){ public void setTypeface(Typeface tf) {
textView.setTypeface(tf); textView.setTypeface(tf);
} }

View File

@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.all.pdfreader.pro.app.PRApp import com.all.pdfreader.pro.app.PRApp
import com.all.pdfreader.pro.app.model.FileActionEvent import com.all.pdfreader.pro.app.model.FileActionEvent
import com.all.pdfreader.pro.app.room.entity.BookmarkEntity
import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity import com.all.pdfreader.pro.app.room.entity.PdfDocumentEntity
import com.all.pdfreader.pro.app.room.repository.PdfRepository 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.AppUtils.generateFastThumbnail
@ -120,8 +121,7 @@ class PdfViewModel : ViewModel() {
val newThumbnail = generateFastThumbnail(context, file) val newThumbnail = generateFastThumbnail(context, file)
if (newThumbnail != null && document.thumbnailPath != newThumbnail) { if (newThumbnail != null && document.thumbnailPath != newThumbnail) {
pdfRepository.updateThumbnailPath( pdfRepository.updateThumbnailPath(
document.filePath, document.filePath, newThumbnail
newThumbnail
) )
Log.d("ocean", "✅ 缩略图已更新") Log.d("ocean", "✅ 缩略图已更新")
} }
@ -146,8 +146,7 @@ class PdfViewModel : ViewModel() {
} }
_fileActionEvent.postValue( _fileActionEvent.postValue(
FileActionEvent.SetPassword( FileActionEvent.SetPassword(
FileActionEvent.SetPassword.Status.COMPLETE, FileActionEvent.SetPassword.Status.COMPLETE, success
success
) )
) )
} }
@ -165,7 +164,8 @@ class PdfViewModel : ViewModel() {
pdfRepository.updateIsPassword(filePath, false) pdfRepository.updateIsPassword(filePath, false)
val document = pdfRepository.getDocumentByPath(filePath) val document = pdfRepository.getDocumentByPath(filePath)
if (document?.thumbnailPath.isNullOrEmpty()) { if (document?.thumbnailPath.isNullOrEmpty()) {
val newThumbnail = generateFastThumbnail(PRApp.getContext(), File(filePath)) val newThumbnail =
generateFastThumbnail(PRApp.getContext(), File(filePath))
Log.d("ocean", "最新图片:$newThumbnail") Log.d("ocean", "最新图片:$newThumbnail")
if (!newThumbnail.isNullOrEmpty() && filePath != newThumbnail) { if (!newThumbnail.isNullOrEmpty() && filePath != newThumbnail) {
pdfRepository.updateThumbnailPath(filePath, newThumbnail) pdfRepository.updateThumbnailPath(filePath, newThumbnail)
@ -181,8 +181,7 @@ class PdfViewModel : ViewModel() {
_fileActionEvent.postValue( _fileActionEvent.postValue(
FileActionEvent.RemovePassword( FileActionEvent.RemovePassword(
FileActionEvent.RemovePassword.Status.COMPLETE, FileActionEvent.RemovePassword.Status.COMPLETE, success
success
) )
) )
} }
@ -193,4 +192,44 @@ class PdfViewModel : ViewModel() {
_fileActionEvent.postValue(FileActionEvent.NoticeReload) _fileActionEvent.postValue(FileActionEvent.NoticeReload)
} }
} }
/**
* 书签相关方法
*/
private val _pdfBookmark = MutableLiveData<List<BookmarkEntity>>()
val pdfBookmark: LiveData<List<BookmarkEntity>> = _pdfBookmark
fun getBookmarks(filePath: String) {
viewModelScope.launch {
Log.d("ocean", "getBookmarks->filePath: $filePath")
pdfRepository.getBookmarksByPdf(filePath).collect { bookmarks ->
_pdfBookmark.value = bookmarks
}
}
}
fun addBookMark(bookmark: BookmarkEntity) {
viewModelScope.launch {
Log.d("ocean", "addBookMarks->bookmark: $bookmark")
val id = pdfRepository.addBookmark(bookmark)
val success = id != -1L//插入成功,会返回 新生成的主键 id
_fileActionEvent.postValue(FileActionEvent.AddBookmark(success))
}
}
fun deleteBookMark(bookmark: BookmarkEntity) {
viewModelScope.launch {
val int = pdfRepository.deleteBookmark(bookmark)
val success = int > 0//受影响行数大于0
_fileActionEvent.postValue(FileActionEvent.DeleteBookmark(success))
}
}
fun deleteAllBookmark(filePath: String) {
viewModelScope.launch {
val int = pdfRepository.deleteAllBookmark(filePath)
val success = int > 0
_fileActionEvent.postValue(FileActionEvent.DeleteAllBookmark(success))
}
}
} }

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="M34.5,511.3c0,-79.5 -0.3,-159.4 0,-238.9 0.3,-42.7 8.5,-84 27.3,-122.5 32.4,-66.9 87.7,-105.1 159.1,-118.8 33.8,-6.5 108.9,-8.2 143.7,-8.5 102.4,-1 233.1,-0.7 335.5,-0.3 44,0.3 88.1,1 130.4,15 85.7,28.3 135.2,88.4 152.2,175.4 4.8,23.9 6.5,48.5 6.5,73 0.7,155 0.3,309.9 0,464.9 0,42.7 -8.2,84 -26.6,122.9 -32.4,67.9 -88.1,106.2 -160.4,120.8 -23.6,4.8 -47.8,7.2 -71.7,7.5 -125.3,0.7 -319.1,0.3 -444.8,0 -43.7,0 -86,-8.2 -125.6,-27.6 -67.9,-33.5 -105.5,-89.8 -119.5,-162.5 -4.4,-23.9 -6.1,-48.5 -6.5,-73 -0.3,-75.8 0,-151.6 0.3,-227.3zM518.1,367.3c-3.1,2.7 -5.8,5.1 -8.5,7.2 -29,26.6 -58,53.2 -87,80.2 -15.7,14.7 -33.8,20.5 -55,15.4 -27.3,-6.5 -43.7,-29 -43.7,-59.1L323.9,104.8v-14c-16,2 -70.3,2.7 -84.3,5.5 -65.2,11.6 -110.6,47.1 -127.3,112.6 -6.1,24.9 -9.2,51.2 -9.6,76.8 -0.7,150.9 -0.7,301.4 0,452.3 0,21.5 2.4,43.3 6.5,64.5 11.3,58 43.3,100.4 101.4,117.8 24.6,7.5 50.9,11.6 76.1,11.9 125.6,1.4 319.1,0.7 444.8,0.3 17.7,0 35.5,-1.4 52.9,-4.4 65.2,-11.3 110.6,-46.8 127.3,-112.3 6.5,-25.3 9.2,-51.9 9.6,-77.8 1,-150.5 0.7,-300.7 0,-451.2 0,-24.9 -2.7,-50.5 -8.5,-74.8 -19.8,-83.3 -116.4,-119.8 -201,-118.8L711.7,411.6c0,36.5 -26.3,62.1 -61.1,60.1 -16,-1 -28.7,-9.2 -40.3,-19.8 -30.7,-28 -61.4,-56 -92.2,-84.7zM642,92.5h-247.8v294.9c28.7,-26.3 55.6,-51.5 82.9,-76.5 24.6,-22.5 56.7,-22.9 81.6,0 19.8,18.1 39.3,36.2 58.7,54.3 7.9,7.2 15.4,14 24.6,22.2L642,92.5z" />
<path
android:fillColor="#ffffff"
android:pathData="M795.3,661.2h-58.7c0,-19.5 0,-39.3 -0.3,-58.7 0,-6.8 -1.7,-14.3 -4.8,-20.1 -7.2,-14 -22.9,-20.1 -38.2,-16.4 -14.3,3.4 -25.6,17.7 -25.6,34.1 -0.3,20.5 0,41 0,61.4 -19.5,0 -39.3,0 -58.7,0.3 -6.8,0 -14.3,1.7 -20.1,4.8 -14,7.2 -20.1,22.9 -16.4,38.2 3.4,14.3 17.7,25.6 34.1,25.6 20.5,0.3 41,0 61.4,0v58c0,22.2 14.3,37.9 34.1,38.2 20.1,0.3 34.5,-15 34.5,-37.5V730.5h58.4c22.2,0 37.9,-14.3 38.2,-34.1 0,-20.5 -15.4,-34.8 -37.9,-35.2z" />
</vector>

View File

@ -0,0 +1,22 @@
<?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"
android:viewportHeight="24">
<path
android:pathData="M12,5v14"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@android:color/transparent"
android:strokeLineCap="round" />
<path
android:pathData="M5,12h14"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@android:color/transparent"
android:strokeLineCap="round" />
</vector>

View File

@ -0,0 +1,22 @@
<?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"
android:viewportHeight="24">
<path
android:pathData="M12,5v14"
android:strokeWidth="2"
android:strokeColor="@color/white"
android:fillColor="@android:color/transparent"
android:strokeLineCap="round" />
<path
android:pathData="M5,12h14"
android:strokeWidth="2"
android:strokeColor="@color/white"
android:fillColor="@android:color/transparent"
android:strokeLineCap="round" />
</vector>

View File

@ -0,0 +1,17 @@
<?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"
android:viewportHeight="24">
<!-- 书签外框 -->
<path
android:pathData="M6,4h12v16l-6,-4l-6,4z"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@color/icon_color"
android:strokeLineJoin="round"
android:strokeLineCap="round" />
</vector>

View File

@ -0,0 +1,26 @@
<?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"
android:viewportHeight="24">
<!-- 斜线 1 -->
<path
android:pathData="M6,6L18,18"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@android:color/transparent"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<!-- 斜线 2 -->
<path
android:pathData="M6,18L18,6"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@android:color/transparent"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#E9C5C5"/>
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#E6E6E6" /> <!-- 默认颜色 -->
<corners android:radius="24dp" />
</shape>

View File

@ -5,7 +5,7 @@
<item android:state_pressed="true"> <item android:state_pressed="true">
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="#3B5C8E"/> <!-- 按下颜色:深一点 --> <solid android:color="#3B5C8E"/> <!-- 按下颜色:深一点 -->
<corners android:radius="12dp"/> <corners android:radius="24dp"/>
</shape> </shape>
</item> </item>
@ -13,7 +13,7 @@
<item> <item>
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="#4E78BA"/> <!-- 默认颜色 --> <solid android:color="#4E78BA"/> <!-- 默认颜色 -->
<corners android:radius="12dp"/> <corners android:radius="24dp"/>
</shape> </shape>
</item> </item>

View File

@ -5,7 +5,7 @@
<item android:state_pressed="true"> <item android:state_pressed="true">
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="#ED343B"/> <!-- 按下颜色:深一点 --> <solid android:color="#ED343B"/> <!-- 按下颜色:深一点 -->
<corners android:radius="12dp"/> <corners android:radius="24dp"/>
</shape> </shape>
</item> </item>
@ -13,7 +13,7 @@
<item> <item>
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="#F1494F"/> <!-- 默认颜色 --> <solid android:color="#F1494F"/> <!-- 默认颜色 -->
<corners android:radius="12dp"/> <corners android:radius="24dp"/>
</shape> </shape>
</item> </item>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/red" />
</shape>

View File

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

View File

@ -0,0 +1,26 @@
<?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"
android:viewportHeight="24">
<!-- 铅笔主体 -->
<path
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25z"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@android:color/transparent"
android:strokeLineJoin="round"
android:strokeLineCap="round" />
<!-- 铅笔头 -->
<path
android:pathData="M20.71,7.04a1,1 0 0 0 0,-1.41l-2.34,-2.34a1,1 0 0 0 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:fillColor="@android:color/transparent"
android:strokeLineJoin="round"
android:strokeLineCap="round" />
</vector>

View File

@ -0,0 +1,35 @@
<?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"
android:viewportHeight="24">
<!-- 外框 -->
<path
android:fillColor="@android:color/transparent"
android:pathData="M5,4h14v16h-14z"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:pathData="M8,8h8"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:strokeLineCap="round" />
<path
android:pathData="M8,12h8"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:strokeLineCap="round" />
<path
android:pathData="M8,16h5"
android:strokeWidth="2"
android:strokeColor="@color/icon_color"
android:strokeLineCap="round" />
</vector>

View File

@ -113,18 +113,18 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopMedium"
android:text="@string/notice" android:text="@string/notice"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="14sp" /> android:textSize="14sp" />
<TextView <TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
style="@style/TextViewFont_PopRegular"
android:maxLines="2" android:maxLines="2"
android:text="@string/permission_notice" android:text="@string/permission_notice"
android:textColor="@color/black_60" android:textColor="@color/black_60"
@ -139,10 +139,10 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
style="@style/TextViewFont_PopSemiBold"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/dr_click_btn_bg" android:background="@drawable/dr_click_btn_bg"
style="@style/TextViewFont_PopSemiBold"
android:paddingStart="24dp" android:paddingStart="24dp"
android:paddingTop="4dp" android:paddingTop="4dp"
android:paddingEnd="24dp" android:paddingEnd="24dp"
@ -173,9 +173,10 @@
<TextView <TextView
android:id="@+id/home_tv" android:id="@+id/home_tv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopRegular" android:layout_marginTop="2dp"
android:text="@string/home" android:text="@string/home"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="14sp" /> android:textSize="14sp" />
@ -197,9 +198,10 @@
<TextView <TextView
android:id="@+id/recently_tv" android:id="@+id/recently_tv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopRegular" android:layout_marginTop="2dp"
android:text="@string/recently" android:text="@string/recently"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="14sp" /> android:textSize="14sp" />
@ -221,9 +223,10 @@
<TextView <TextView
android:id="@+id/favorite_tv" android:id="@+id/favorite_tv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopRegular" android:layout_marginTop="2dp"
android:text="@string/favorite" android:text="@string/favorite"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="14sp" /> android:textSize="14sp" />
@ -245,9 +248,10 @@
<TextView <TextView
android:id="@+id/tools_tv" android:id="@+id/tools_tv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopRegular" android:layout_marginTop="2dp"
android:text="@string/tools" android:text="@string/tools"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="14sp" /> android:textSize="14sp" />

View File

@ -77,19 +77,20 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal|bottom" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<ImageView <ImageView
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:layout_marginTop="4dp"
android:src="@drawable/pdf_view_mode" /> android:src="@drawable/pdf_view_mode" />
<TextView <TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="2dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/view_model" android:text="@string/view_model"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="12sp" /> android:textSize="12sp" />
@ -101,20 +102,21 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal|bottom" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<ImageView <ImageView
android:id="@+id/eyeProtectIv" android:id="@+id/eyeProtectIv"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:layout_marginTop="4dp"
android:src="@drawable/eye_protect" /> android:src="@drawable/eye_protect" />
<TextView <TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="2dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/eye_protect" android:text="@string/eye_protect"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="12sp" /> android:textSize="12sp" />
@ -125,19 +127,41 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal|bottom" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<RelativeLayout
android:layout_width="24dp"
android:layout_height="24dp">
<ImageView <ImageView
android:id="@+id/bookmarksIv"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="@drawable/add_bookmarks" /> android:src="@drawable/add_bookmarks" />
<TextView <TextView
android:id="@+id/bookmarksHint"
style="@style/TextViewFont_PopRegular"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_alignParentEnd="true"
android:background="@drawable/dr_dot_red"
android:gravity="center"
android:padding="1dp"
android:text="1"
android:textColor="@color/white"
android:textSize="8sp" />
</RelativeLayout>
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="2dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/bookmarks" android:text="@string/bookmarks"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="12sp" /> android:textSize="12sp" />
@ -148,19 +172,20 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal|bottom" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<ImageView <ImageView
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:layout_marginTop="4dp"
android:src="@drawable/share" /> android:src="@drawable/share" />
<TextView <TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="2dp"
style="@style/TextViewFont_PopRegular"
android:text="@string/share_file" android:text="@string/share_file"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="12sp" /> android:textSize="12sp" />

View File

@ -0,0 +1,74 @@
<?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="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:background="@drawable/dr_item_bookmark_page_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:src="@drawable/page_icon" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/titleTv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Page 1"
android:textColor="@color/icon_color"
android:textSize="16sp" />
<TextView
android:id="@+id/descTv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="(#1)"
android:textColor="@color/grey_text_color"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/editBtn"
android:layout_width="44dp"
android:layout_height="44dp"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/edit_icon" />
</LinearLayout>
<LinearLayout
android:id="@+id/deleteBtn"
android:layout_width="44dp"
android:layout_height="44dp"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/delete_cha_icon" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:fitsSystemWindows="true"
android:paddingBottom="16dp"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -24,15 +25,155 @@
android:layout_margin="16dp" android:layout_margin="16dp"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView <TextView
android:id="@+id/tvTitle" android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextViewFont_PopSemiBold" style="@style/TextViewFont_PopSemiBold"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/bookmarks" android:text="@string/bookmarks"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="18sp" /> android:textSize="18sp" />
<LinearLayout
android:id="@+id/addBtn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/dr_click_btn_red_bg"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:visibility="visible">
<ImageView
android:id="@+id/addIv"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/add_icon_white" />
<TextView
android:id="@+id/addTv"
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@color/line_color" />
<LinearLayout
android:id="@+id/noBookmarksPageLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:visibility="visible">
<LinearLayout
android:layout_width="68dp"
android:layout_height="68dp"
android:layout_marginTop="8dp"
android:background="@drawable/dr_bookmarks_bg"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/add_bookmarks_white" />
</LinearLayout>
<TextView
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/no_bookmarks_page"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="@string/no_bookmarks_page_desc"
android:textColor="@color/grey_text_color"
android:textSize="14sp" />
<LinearLayout
android:id="@+id/addBookmarkBtn"
android:layout_width="wrap_content"
android:layout_height="44dp"
android:layout_marginTop="24dp"
android:background="@drawable/dr_click_btn_red_bg"
android:gravity="center"
android:paddingStart="24dp"
android:paddingEnd="24dp">
<TextView
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_bookmark"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/bookmarksDisplayLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/bookmarksPageRv"
android:layout_width="match_parent"
android:layout_height="192dp"
android:paddingBottom="8dp"
android:scrollbars="vertical"
tools:itemCount="2"
tools:listitem="@layout/adapter_item_bookmark_page" />
<LinearLayout
android:id="@+id/deleteALLPageBtn"
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/file_delete" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/delete_all_pages"
android:textColor="@color/grey_text_color"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -6,22 +6,24 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/deleteTitleTv"
style="@style/TextViewFont_PopSemiBold"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="24dp" android:layout_margin="24dp"
style="@style/TextViewFont_PopSemiBold" android:text="@string/app_name"
android:text="@string/delete_file_title"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="18sp" /> android:textSize="18sp" />
<TextView <TextView
android:id="@+id/deleteDescTv"
style="@style/TextViewFont_PopRegular"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="24dp" android:layout_marginStart="24dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
style="@style/TextViewFont_PopRegular" android:text="@string/app_name"
android:text="@string/delete_file_desc"
android:textColor="@color/black_80" android:textColor="@color/black_80"
android:textSize="16sp" /> android:textSize="16sp" />
@ -41,9 +43,9 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
style="@style/TextViewFont_PopSemiBold"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopSemiBold"
android:text="@string/cancel" android:text="@string/cancel"
android:textColor="@color/black_60" android:textColor="@color/black_60"
android:textSize="16sp" /> android:textSize="16sp" />
@ -59,9 +61,9 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
style="@style/TextViewFont_PopSemiBold"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopSemiBold"
android:text="@string/delete" android:text="@string/delete"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="16sp" /> android:textSize="16sp" />

View File

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp" android:padding="16dp"
tools:ignore="UseCompoundDrawables"> tools:ignore="UseCompoundDrawables">
@ -36,10 +37,10 @@
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<TextView <TextView
style="@style/TextViewFont_PopSemiBold"
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:layout_marginBottom="8dp"
style="@style/TextViewFont_PopSemiBold"
android:gravity="center" android:gravity="center"
android:text="@string/permission_required" android:text="@string/permission_required"
android:textColor="@color/black" android:textColor="@color/black"
@ -47,10 +48,10 @@
<TextView <TextView
android:id="@+id/pr_desc" android:id="@+id/pr_desc"
style="@style/TextViewFont_PopRegular"
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:layout_marginBottom="8dp"
style="@style/TextViewFont_PopRegular"
android:gravity="center" android:gravity="center"
android:text="@string/permission_required_desc_1" android:text="@string/permission_required_desc_1"
android:textColor="@color/black_80" android:textColor="@color/black_80"
@ -73,10 +74,10 @@
android:paddingEnd="16dp"> android:paddingEnd="16dp">
<TextView <TextView
style="@style/TextViewFont_PopRegular"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
style="@style/TextViewFont_PopRegular"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/permission_required_desc_2" android:text="@string/permission_required_desc_2"
android:textColor="@color/black_80" android:textColor="@color/black_80"
@ -104,9 +105,9 @@
android:gravity="center"> android:gravity="center">
<TextView <TextView
style="@style/TextViewFont_PopSemiBold"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/TextViewFont_PopSemiBold"
android:text="@string/allow_access" android:text="@string/allow_access"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="16sp" /> android:textSize="16sp" />

View File

@ -2,6 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView

View File

@ -4,6 +4,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:fitsSystemWindows="true"
android:paddingBottom="16dp"> android:paddingBottom="16dp">
<LinearLayout <LinearLayout

View File

@ -16,4 +16,5 @@
<color name="grey_text_color">#666666</color> <color name="grey_text_color">#666666</color>
<color name="eye_protection_color">#80FFD699</color> <color name="eye_protection_color">#80FFD699</color>
<color name="icon_color">#636366</color> <color name="icon_color">#636366</color>
<color name="red">#F1494F</color>
</resources> </resources>

View File

@ -29,6 +29,8 @@
<string name="unlock">Unlock</string> <string name="unlock">Unlock</string>
<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="no_bookmarks_page">No Bookmarks Page</string>
<string name="no_bookmarks_page_desc">You haven\'t added any page to your bookmarks.Please add pages to see them here.</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>
@ -45,9 +47,13 @@
<string name="share_file">Share</string> <string name="share_file">Share</string>
<string name="print_pdf">Print</string> <string name="print_pdf">Print</string>
<string name="added_to_favorites">Added to Favorite</string> <string name="added_to_favorites">Added to Favorite</string>
<string name="add_bookmark">Add Bookmark</string>
<string name="added">Added</string>
<string name="add">Add</string>
<string name="removed_from_favorites">Removed from Favorites</string> <string name="removed_from_favorites">Removed from Favorites</string>
<string name="delete_file">Delete File</string> <string name="delete_file">Delete File</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="delete_all_pages">Delete All Pages</string>
<string name="set_password">Set Password</string> <string name="set_password">Set Password</string>
<string name="set_password_successfully">Set Password successfully</string> <string name="set_password_successfully">Set Password successfully</string>
<string name="set_password_failed">Set Password failed</string> <string name="set_password_failed">Set Password failed</string>
@ -101,4 +107,10 @@
<string name="color_inversion">color inversion</string> <string name="color_inversion">color inversion</string>
<string name="horizontal">Horizontal</string> <string name="horizontal">Horizontal</string>
<string name="vertical">Vertical</string> <string name="vertical">Vertical</string>
<string name="page">Page</string>
<string name="bookmark_add_success">Bookmark added successfully</string>
<string name="bookmark_add_fail">Failed to add bookmark</string>
<string name="bookmark_remove">Bookmark remove</string>
<string name="delete_bookmarks_title">Delete Bookmarks</string>
<string name="delete_bookmarks_desc">Are you sure you want to delete all Bookmarks?</string>
</resources> </resources>