Commit 5166b6dc authored by wanglei's avatar wanglei

初始化

parent 805851f9
...@@ -44,6 +44,7 @@ dependencies { ...@@ -44,6 +44,7 @@ dependencies {
implementation(libs.androidx.activity) implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout) implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.swiperefreshlayout) implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.tools.core)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.espresso.core)
...@@ -57,4 +58,5 @@ dependencies { ...@@ -57,4 +58,5 @@ dependencies {
//Pdf库 //Pdf库
implementation("com.tom-roush:pdfbox-android:2.0.27.0") implementation("com.tom-roush:pdfbox-android:2.0.27.0")
api(project(":pdflibrary"))
} }
\ No newline at end of file
...@@ -31,6 +31,13 @@ ...@@ -31,6 +31,13 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ui.pdf.PdfActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
</activity>
</application> </application>
</manifest> </manifest>
\ No newline at end of file
...@@ -25,6 +25,14 @@ object ConstObject { ...@@ -25,6 +25,14 @@ object ConstObject {
const val UI_SORT_NAME_Z_A = "ui_sort_name_z_a" const val UI_SORT_NAME_Z_A = "ui_sort_name_z_a"
var haveGuideGesture = false
get() {
return AppPreferences.getInstance().getBoolean("haveGuideGesture", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("haveGuideGesture", value, true)
}
var haveSaveDemo = false var haveSaveDemo = false
get() { get() {
return AppPreferences.getInstance().getBoolean("haveSaveDemo", field) return AppPreferences.getInstance().getBoolean("haveSaveDemo", field)
...@@ -42,7 +50,7 @@ object ConstObject { ...@@ -42,7 +50,7 @@ object ConstObject {
AppPreferences.getInstance().put("modeNight", value, true) AppPreferences.getInstance().put("modeNight", value, true)
} }
var appLanguageSp = Locale.ENGLISH.language var appLanguageSp = Locale.getDefault().language + "_" + Locale.getDefault().country
get() { get() {
return AppPreferences.getInstance().getString("appLanguageSp", field) return AppPreferences.getInstance().getString("appLanguageSp", field)
} }
......
package com.base.pdfreader2.bean
import android.graphics.drawable.Drawable
data class PdfPageBean(
val pageIndex: Int = 0,
var pageDrawable: Drawable? = null
) {
var isSelect: Boolean = false
}
\ No newline at end of file
package com.base.pdfreader2.ui.main package com.base.pdfreader2.ui.main
import android.app.Activity import android.app.Activity
import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.view.View import android.view.View
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
...@@ -18,6 +19,7 @@ import com.base.pdfreader2.bean.ConstObject.RECENT_DATA_TYPE ...@@ -18,6 +19,7 @@ import com.base.pdfreader2.bean.ConstObject.RECENT_DATA_TYPE
import com.base.pdfreader2.bean.DocumentBean import com.base.pdfreader2.bean.DocumentBean
import com.base.pdfreader2.databinding.ActivityMainBinding import com.base.pdfreader2.databinding.ActivityMainBinding
import com.base.pdfreader2.helper.BaseActivity import com.base.pdfreader2.helper.BaseActivity
import com.base.pdfreader2.ui.pdf.PdfActivity
import com.base.pdfreader2.ui.view.DialogView.showSortDialog import com.base.pdfreader2.ui.view.DialogView.showSortDialog
import com.base.pdfreader2.utils.BarUtils import com.base.pdfreader2.utils.BarUtils
import com.base.pdfreader2.utils.LogEx import com.base.pdfreader2.utils.LogEx
...@@ -357,9 +359,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() { ...@@ -357,9 +359,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
fun Activity.jumpDocument(item: DocumentBean) { fun Activity.jumpDocument(item: DocumentBean) {
if (item.type == DocumentBean.TYPE_PDF) { if (item.type == DocumentBean.TYPE_PDF) {
if (item.state == 0) { if (item.state == 0) {
// startActivity(Intent(this, PdfActivity::class.java).apply { startActivity(Intent(this, PdfActivity::class.java).apply {
// putExtra("path", item.path) putExtra("path", item.path)
// }) })
} }
if (item.state == 1) { if (item.state == 1) {
// showPdfPwdDialog( // showPdfPwdDialog(
......
package com.base.pdfreader2.ui.pdf
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.util.DisplayMetrics
import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.view.inputmethod.EditorInfo
import androidx.activity.addCallback
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.MuPDFReaderView
import com.artifex.mupdfdemo.MuPDFView
import com.artifex.mupdfdemo.SearchTask
import com.artifex.mupdfdemo.SearchTaskResult
import com.base.pdfreader2.R
import com.base.pdfreader2.bean.ConstObject.haveGuideGesture
import com.base.pdfreader2.bean.PdfPageBean
import com.base.pdfreader2.databinding.ActivityPdfBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import com.base.pdfreader2.helper.BaseActivity
import com.base.pdfreader2.helper.MyApplication
import com.base.pdfreader2.ui.view.PdfDialog.showPdfMoreDialog
import com.base.pdfreader2.utils.KeyBoardUtils.hideKeyboard
import com.base.pdfreader2.utils.KeyBoardUtils.showKeyBoard
import com.base.pdfreader2.utils.LogEx
import com.base.pdfreader2.utils.SpStringUtils
import com.base.pdfreader2.utils.SpStringUtils.LAST_VIEW_KEY
import com.base.pdfreader2.utils.ToastUtils.toast
import com.artifex.mupdfdemo.Annotation
import com.artifex.mupdfdemo.Hit
import com.artifex.mupdfdemo.MuPDFPageAdapter
import com.artifex.mupdfdemo.MuPDFReaderViewListener
class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {
private val TAG = "PdfActivity"
private lateinit var pdfPresenter: PdfPresenter
private lateinit var pdfPageAdapter: PdfPagerAdapter
private var muPDFCore: MuPDFCore? = null // 加载mupdf.so文件
private var searchTask: SearchTask? = null
private var uiMode = UI_MODE_NORMAL
private var saveMode = ""
private var path: String = ""
private var uri: String? = null
private var assets: String? = null
private var density = 0f
override val binding: ActivityPdfBinding by lazy {
ActivityPdfBinding.inflate(layoutInflater)
}
override fun onResume() {
super.onResume()
updateAppLanguage(MyApplication.pdfLanguage, TAG) {
MyApplication.pdfLanguage = it
}
}
override fun onPause() {
super.onPause()
searchTask?.stop()
}
override fun onDestroy() {
super.onDestroy()
muPDFCore?.onDestroy()
// AdmobNativeUtils.onDestroy()
}
override fun initView() {
val needRecreate = checkNeedRecreate(MyApplication.pdfLanguage)
if (needRecreate) return
val metrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(metrics)
density = metrics.density
path = intent.extras?.getString("path") ?: ""
uri = intent.extras?.getString("uri")
assets = intent.extras?.getString("assets") ?: ""
LogEx.logDebug(TAG, "path=$path")
LogEx.logDebug(TAG, "uri=$uri")
val file = File(path)
binding.tvPdfName.text = file.name
pdfPresenter = PdfPresenter(this, this)
initAdapter()
changeNormalUI()
runCatching {
muPDFCore = pdfPresenter.openFile(path, uri)
}
// 搜索设为空
SearchTaskResult.set(null)
if (muPDFCore?.needsPassword() == true) {
val pwd = intent.extras?.getString("pwd") ?: ""
val flag = muPDFCore?.authenticatePassword(pwd) ?: false
if (flag) {
pdfPresenter.password = pwd
pdfPageAdapter.setPassword(pwd)
createPdfUI()
muPDFCore?.countPages()?.let { pdfPresenter.iniPdfPage(it) }
SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_/_${System.currentTimeMillis()}")
} else {
toast("unknown error")
finish()
}
} else {
createPdfUI()
muPDFCore?.countPages()?.let { pdfPresenter.iniPdfPage(it) }
SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_/_${System.currentTimeMillis()}")
}
if (!haveGuideGesture) {
binding.flGuideGesture.visibility = View.VISIBLE
lifecycleScope.launch(Dispatchers.Main) {
delay(2000)
binding.flGuideGesture.visibility = View.GONE
}
}
// AdmobNativeUtils.showNativeAd(this, binding.flAd, R.layout.layout_admob_document_in)
}
override fun jumpPage(pageIndex: Int) {
super.jumpPage(pageIndex)
binding.mupdfReaderView.displayedViewIndex = pageIndex
}
private fun iniSetVerticalSeekbar(max: Int) {
binding.verticalSeekbar.visibility = View.VISIBLE
binding.verticalSeekbar.showThumb = true
binding.verticalSeekbar.barBackgroundStartColor = Color.TRANSPARENT
binding.verticalSeekbar.thumbContainerColor = Color.TRANSPARENT
binding.verticalSeekbar.thumbPlaceholderDrawable =
ContextCompat.getDrawable(this, R.mipmap.fanye)
if (binding.verticalSeekbar.maxValue != max - 1) {
binding.verticalSeekbar.maxValue = max - 1
}
}
private fun setVerticalSeekbar(current: Int, max: Int) {
val process = max - current
LogEx.logDebug(TAG, "process=$process $current $max")
binding.verticalSeekbar.progress = process
}
override fun initListener() {
val needRecreate = checkNeedRecreate(MyApplication.pdfLanguage)
if (needRecreate) return
onBackPressedDispatcher.addCallback {
hideKeyboard(binding.editSearch)
if (uiMode == UI_MODE_SEARCH) {
changeNormalUI()
cancelSearch()
return@addCallback
}
if (uiMode == UI_MODE_EDITE_SELECT) {
changeNormalUI()
cancelOperation()
return@addCallback
}
if (uiMode == UI_MODE_EDITE_SAVE) {
changeNormalUI()
cancelOperation()
return@addCallback
}
// if (AdmobHelper.isShowCloseDocumentInter() && isShowCloseDocument()) {
// AdmobInterstitialUtils.showInterstitialAd(this@PdfActivity) {
// if (it) {
// AdmobHelper.lastCloseDocumentShowAd = System.currentTimeMillis()
// }
binding.root.postDelayed({ finishToMain() }, 500)
// }
// } else {
// binding.root.postDelayed({ finishToMain() }, 500)
// }
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.llHighlight.setOnClickListener {
saveMode = SAVE_MODE_HIGHLIGHT
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
}
binding.llGlideLine.setOnClickListener {
saveMode = SAVE_MODE_GLIDE_LINE
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
}
binding.llStrikethrough.setOnClickListener {
saveMode = SAVE_MODE_STRIKETHROUGH
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
}
binding.llPaintingBrush.setOnClickListener {
saveMode = SAVE_MODE_PAINTING_BRUSH
changeEditSelectUI(it)
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Drawing)
}
binding.ivWancheng.setOnClickListener {
changeEditSaveUI()
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
}
binding.ivBianji.setOnClickListener {
bianJiScaleXiao {
changeEditSaveUI()
}
}
binding.ivSearch.setOnClickListener {
bianJiScaleXiao {
changeSearchUI()
showKeyBoard(binding.editSearch)
}
}
binding.editSearch.addTextChangedListener {
if (SearchTaskResult.get() != null && it.toString() != SearchTaskResult.get().txt) {
SearchTaskResult.set(null as SearchTaskResult?)
binding.mupdfReaderView.resetupChildren()
}
}
binding.editSearch.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
search(1)
}
false
}
binding.tvBtnSave.setOnClickListener {
// PdfLoadingActivity.muPDFCore = muPDFCore
// reallySave()
// startActivity(Intent(this, PdfLoadingActivity::class.java).apply {
// putExtra("doWhat", DO_SAVE_PDF)
// putExtra("srcPath", path)
// })
finish()
}
binding.ivXuanzhuan.setOnClickListener {
switchOrientation()
}
binding.verticalSeekbar.setOnReleaseListener { progress ->
LogEx.logDebug(TAG, "progress=$progress")
val total = muPDFCore?.countPages() ?: 0
val pageIndex = total - 1 - progress
binding.mupdfReaderView.displayedViewIndex = pageIndex
}
binding.flGuideGesture.setOnClickListener {
haveGuideGesture = true
binding.flGuideGesture.visibility = View.GONE
}
binding.ivMore.setOnClickListener {
val count = muPDFCore?.countPages() ?: 0
showPdfMoreDialog(this, count - 1, path)
}
}
/**
*
*/
private fun reallySave() {
var success: Boolean = false
val pageView = binding.mupdfReaderView.displayedView as MuPDFView
when (saveMode) {
SAVE_MODE_HIGHLIGHT -> {
success = pageView.markupSelection(Annotation.Type.HIGHLIGHT)
}
SAVE_MODE_GLIDE_LINE -> {
success = pageView.markupSelection(Annotation.Type.UNDERLINE)
}
SAVE_MODE_STRIKETHROUGH -> {
success = pageView.markupSelection(Annotation.Type.STRIKEOUT)
}
SAVE_MODE_PAINTING_BRUSH -> {
success = pageView.saveDraw()
}
}
if (!success) {
toast("nothing to save")
return
}
}
private fun cancelOperation() {
val pageView = binding.mupdfReaderView.displayedView as MuPDFView?
if (pageView != null) {
pageView.deselectAnnotation()
pageView.deleteSelectedAnnotation()
pageView.deselectText()
pageView.cancelDraw()
}
binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
}
private fun cancelSearch() {
SearchTaskResult.set(null)
binding.mupdfReaderView.resetupChildren()
}
/**
* 有个问题,一旦pdf某页编辑后加个蒙层,搜索功能就是失效了
*/
private fun search(direction: Int) {
this.hideKeyboard(binding.editSearch)
val displayPage: Int = binding.mupdfReaderView.displayedViewIndex
val r = SearchTaskResult.get()
val searchPage = r?.pageNumber ?: -1
searchTask?.go(binding.editSearch.text.toString(), direction, displayPage, searchPage)
}
private fun initAdapter() {
pdfPageAdapter = PdfPagerAdapter(path, uri)
pdfPageAdapter.clickAction = { pageIndex ->
binding.mupdfReaderView.displayedViewIndex = pageIndex
}
binding.rvPager.adapter = pdfPageAdapter
}
private var isShowTopBottomLayout = true
private fun hideTopBottomLayout() {
if (isShowTopBottomLayout) {
isShowTopBottomLayout = false
hideKeyboard(binding.editSearch)
val topAnim: Animation = TranslateAnimation(0f, 0f, 0f, -binding.vAnimatorTop.height.toFloat())
topAnim.setDuration(200)
topAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
binding.vAnimatorTop.visibility = View.GONE
}
})
binding.vAnimatorTop.startAnimation(topAnim)
val bottomAnim: Animation = TranslateAnimation(0f, 0f, 0f, binding.vAnimatorBottom.height.toFloat())
bottomAnim.duration = 200
bottomAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
binding.vAnimatorBottom.visibility = View.GONE
}
})
binding.vAnimatorBottom.startAnimation(bottomAnim)
bianJiScaleXiao()
}
}
private fun showTopBottomLayout() {
if (!isShowTopBottomLayout) {
isShowTopBottomLayout = true
val topAnim: Animation = TranslateAnimation(0f, 0f, -binding.vAnimatorTop.height.toFloat(), 0f)
topAnim.setDuration(200)
topAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
binding.vAnimatorTop.visibility = View.VISIBLE
}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
}
})
binding.vAnimatorTop.startAnimation(topAnim)
val bottomAnim: Animation = TranslateAnimation(0f, 0f, binding.vAnimatorBottom.height.toFloat(), 0f)
bottomAnim.duration = 200
bottomAnim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
binding.vAnimatorBottom.visibility = View.VISIBLE
}
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
}
})
binding.vAnimatorBottom.startAnimation(bottomAnim)
bianJiScaleDa()
}
}
private fun bianJiScaleDa() {
if (binding.ivBianji.scaleX == 0f) {
val scaleXAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleX", 0f, 1.0f)
scaleXAnimator.duration = 200
val scaleYAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleY", 0f, 1.0f)
scaleYAnimator.duration = 200
val animatorSet = AnimatorSet()
animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
animatorSet.start()
}
}
private fun bianJiScaleXiao(endAction: (() -> Unit)? = null) {
if (binding.ivBianji.scaleX == 1f) {
val scaleXAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleX", 1.0f, 0f)
scaleXAnimator.duration = 200
val scaleYAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleY", 1.0f, 0f)
scaleYAnimator.duration = 200
val animatorSet = AnimatorSet()
animatorSet.addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator) = Unit
override fun onAnimationEnd(animation: Animator) {
endAction?.invoke()
}
override fun onAnimationCancel(animation: Animator) = Unit
override fun onAnimationRepeat(animation: Animator) = Unit
})
animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
animatorSet.start()
}
}
/**
* 构建pdf的ui
*/
@SuppressLint("SetTextI18n")
private fun createPdfUI() {
if (muPDFCore == null) return
binding.tvPageCount.text = "1/${muPDFCore?.countPages()}"
binding.mupdfReaderView.setListener(object : MuPDFReaderViewListener {
@SuppressLint("SetTextI18n")
override fun onMoveToChild(i: Int) {
binding.tvPageCount.text = "${i + 1}/${muPDFCore?.countPages()}"
pdfPageAdapter.changeSelectPager(i)
binding.rvPager.scrollToPosition(i)
setVerticalSeekbar(i + 1, muPDFCore?.countPages() ?: 0)
}
override fun onTapMainDocArea() {
if (isShowTopBottomLayout) {
hideTopBottomLayout()
} else {
showTopBottomLayout()
}
}
override fun onDocMotion() {
}
override fun onHit(item: Hit?) {
}
})
binding.mupdfReaderView.adapter = MuPDFPageAdapter(this, {}, muPDFCore)
binding.mupdfReaderView.setBackgroundColor(Color.parseColor("#E0D5FA"))
binding.mupdfReaderView.setHorizontalScrolling(false)
searchTask = object : SearchTask(this, muPDFCore) {
override fun onTextFound(result: SearchTaskResult?) {
SearchTaskResult.set(result)
binding.mupdfReaderView.displayedViewIndex = result?.pageNumber ?: 0
binding.mupdfReaderView.resetupChildren()
}
}
}
/**
* 普通模式
*/
private fun changeNormalUI() {
uiMode = UI_MODE_NORMAL
binding.ivWancheng.visibility = View.GONE
binding.clOperation.visibility = View.GONE
binding.tvBtnSave.visibility = View.GONE
binding.editSearch.visibility = View.INVISIBLE
binding.ivXuanzhuan.visibility = View.VISIBLE
binding.ivSearch.visibility = View.VISIBLE
binding.ivMore.visibility = View.VISIBLE
binding.rvPager.visibility = View.VISIBLE
binding.tvPdfName.visibility = View.VISIBLE
bianJiScaleDa()
}
/**
* 搜索模式UI
*/
private fun changeSearchUI() {
uiMode = UI_MODE_SEARCH
binding.ivXuanzhuan.visibility = View.INVISIBLE
binding.ivMore.visibility = View.GONE
binding.tvPdfName.visibility = View.INVISIBLE
binding.rvPager.visibility = View.GONE
binding.clOperation.visibility = View.GONE
binding.editSearch.visibility = View.VISIBLE
}
/**
* 编辑选择UI模式
*/
private fun changeEditSelectUI(view: View) {
uiMode = UI_MODE_EDITE_SELECT
binding.tvBtnSave.visibility = View.GONE
binding.rvPager.visibility = View.GONE
binding.ivXuanzhuan.visibility = View.INVISIBLE
binding.ivSearch.visibility = View.INVISIBLE
binding.ivMore.visibility = View.INVISIBLE
binding.ivWancheng.visibility = View.VISIBLE
if (binding.llHighlight == view) {
binding.llHighlight.setBackgroundColor(Color.parseColor("#F5F5F5"))
} else {
binding.llHighlight.setBackgroundColor(Color.TRANSPARENT)
}
if (binding.llGlideLine == view) {
binding.llGlideLine.setBackgroundColor(Color.parseColor("#F5F5F5"))
} else {
binding.llGlideLine.setBackgroundColor(Color.TRANSPARENT)
}
if (binding.llStrikethrough == view) {
binding.llStrikethrough.setBackgroundColor(Color.parseColor("#F5F5F5"))
} else {
binding.llStrikethrough.setBackgroundColor(Color.TRANSPARENT)
}
if (binding.llPaintingBrush == view) {
binding.llPaintingBrush.setBackgroundColor(Color.parseColor("#F5F5F5"))
} else {
binding.llPaintingBrush.setBackgroundColor(Color.TRANSPARENT)
}
}
/**
* 编辑保持UI模式
*/
private fun changeEditSaveUI() {
uiMode = UI_MODE_EDITE_SAVE
binding.ivWancheng.visibility = View.INVISIBLE
binding.ivMore.visibility = View.INVISIBLE
binding.ivXuanzhuan.visibility = View.INVISIBLE
binding.ivSearch.visibility = View.INVISIBLE
binding.clOperation.visibility = View.VISIBLE
binding.tvBtnSave.visibility = View.VISIBLE
binding.rvPager.visibility = View.VISIBLE
binding.llHighlight.setBackgroundColor(Color.TRANSPARENT)
binding.llGlideLine.setBackgroundColor(Color.TRANSPARENT)
binding.llStrikethrough.setBackgroundColor(Color.TRANSPARENT)
binding.llPaintingBrush.setBackgroundColor(Color.TRANSPARENT)
}
fun switchOrientation() {
requestedOrientation = if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
} else {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
}
companion object {
const val UI_MODE_NORMAL = 0
const val UI_MODE_SEARCH = 1
const val UI_MODE_EDITE_SELECT = 2
const val UI_MODE_EDITE_SAVE = 3
const val SAVE_MODE_HIGHLIGHT = "Highlight"
const val SAVE_MODE_GLIDE_LINE = "Glide Line"
const val SAVE_MODE_STRIKETHROUGH = "Strikethrough"
const val SAVE_MODE_PAINTING_BRUSH = "Painting Brush"
}
override fun initPdfPageRv(items: List<PdfPageBean>) {
pdfPageAdapter.submitList(items)
pdfPageAdapter.changeSelectPager(0)
iniSetVerticalSeekbar(items.size)
}
}
\ No newline at end of file
package com.base.pdfreader2.ui.pdf
import android.annotation.SuppressLint
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.pdfreader2.R
import com.base.pdfreader2.bean.PdfPageBean
import com.base.pdfreader2.databinding.ItemPdfPagerBinding
import com.base.pdfreader2.databinding.ItemPdfPagerSplitBinding
import com.base.pdfreader2.utils.PdfBoxUtils.getPdfDrawablePage
import com.base.pdfreader2.utils.XmlEx.inflate
import com.chad.library.adapter4.BaseQuickAdapter
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
class PdfPagerAdapter(
val pdfPath: String,
val uri: String? = null,
val itemLayout: Int = R.layout.item_pdf_pager,
) : BaseQuickAdapter<PdfPageBean, PdfPagerAdapter.PdfPagerViewHolder>() {
var mPassword: String? = null
var selectAction: ((enable: Boolean, allSelect: Boolean) -> Unit)? = null
var clickAction: ((pageIndex: Int) -> Unit)? = null
inner class PdfPagerViewHolder(view: View) : ViewHolder(view)
var corePoolSize = 4 // 核心线程数
var maximumPoolSize = 10 // 最大线程数
var keepAliveTime: Long = 120 // 非核心线程空闲存活时间
var threadPoolExecutor = ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
LinkedBlockingQueue()
)
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: PdfPagerViewHolder, position: Int, item: PdfPageBean?) {
if (item == null) return
when (itemLayout) {
R.layout.item_pdf_pager -> {
val binding = ItemPdfPagerBinding.bind(holder.itemView)
val context = holder.itemView.context
binding.tvPagerIndex.isSelected = item.isSelect
binding.tvPagerIndex.text = (item.pageIndex + 1).toString()
binding.flBorder.isSelected = item.isSelect
if (item.pageDrawable != null) {
binding.ivPager.setImageDrawable(item.pageDrawable)
} else {
loadPagerDrawable(context, item, binding.root, binding.ivPager)
}
binding.root.setOnClickListener {
clickAction?.invoke(item.pageIndex)
}
}
R.layout.item_pdf_pager_split -> {
val binding = ItemPdfPagerSplitBinding.bind(holder.itemView)
binding.ivSelector.isSelected = item.isSelect
if (item.pageDrawable != null) {
binding.ivPager.setImageDrawable(item.pageDrawable)
} else {
loadPagerDrawable(context, item, binding.root, binding.ivPager, 1.5f)
}
binding.ivSelector.setOnClickListener {
item.isSelect = !item.isSelect
notifyItemChanged(position, "aaa")
selectAction?.invoke(items.any { it.isSelect }, items.all { it.isSelect })
}
}
}
}
private fun loadPagerDrawable(
context: Context,
item: PdfPageBean,
itemView: View,
iv: ImageView,
scale: Float = 1f
) {
threadPoolExecutor.execute {
runCatching {
val drawable = context.getPdfDrawablePage(context, pdfPath, mPassword, uri, item.pageIndex, scale)
item.pageDrawable = drawable
itemView.post {
item.pageDrawable?.let {
iv.setImageDrawable(it)
}
}
}
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): PdfPagerViewHolder {
return PdfPagerViewHolder(itemLayout.inflate(parent))
}
@SuppressLint("NotifyDataSetChanged")
fun toggleSelect(select: Boolean) {
items.forEach { it.isSelect = select }
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun changeSelectPager(page: Int) {
runCatching {
items.forEach { it.isSelect = false }
items[page].isSelect = true
}
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun setPassword(password: String) {
mPassword = password
notifyDataSetChanged()
}
}
\ No newline at end of file
package com.base.pdfreader2.ui.pdf
import android.content.Context
import android.net.Uri
import android.os.Environment
import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.OutlineActivityData
import com.base.pdfreader2.R
import com.base.pdfreader2.bean.ConstObject.MIME_TYPE_PDF
import com.base.pdfreader2.bean.PdfPageBean
import com.base.pdfreader2.utils.LogEx
import com.base.pdfreader2.utils.PdfBoxUtils.getNumberOfPages
import com.base.pdfreader2.utils.UriUtils.readFileToByteArray
import com.tom_roush.pdfbox.multipdf.PDFMergerUtility
import com.tom_roush.pdfbox.pdmodel.PDDocument
import java.io.File
class PdfPresenter(
val context: Context,
val pdfView: PdfView? = null
) {
private val TAG = "PdfPresenter"
var password: String? = null
fun openFile(path: String, uri: String? = null): MuPDFCore? {
var muPDFCore: MuPDFCore? = null
try {
muPDFCore = if (uri == null) MuPDFCore(context, path) else MuPDFCore(
context,
readFileToByteArray(context, Uri.parse(uri)),
MIME_TYPE_PDF
)
// 新建:删除旧的目录数据
OutlineActivityData.set(null)
} catch (e: java.lang.Exception) {
return null
} catch (e: OutOfMemoryError) {
return null
}
return muPDFCore
}
fun iniPdfPage(filePath: String, uri: String? = null) {
val list = arrayListOf<PdfPageBean>()
val number = context.getNumberOfPages(filePath, password, uri)
repeat(number) {
list.add(PdfPageBean(it))
}
pdfView?.initPdfPageRv(list)
}
fun iniPdfPage(pageCount: Int) {
val list = arrayListOf<PdfPageBean>()
repeat(pageCount) {
list.add(PdfPageBean(it))
}
pdfView?.initPdfPageRv(list)
}
fun splitPdf(
srcPath: String,
newPath: String,
splitIndex: List<Int>,
finishAction: (newFile: File?) -> Unit
) = Thread {
try {
// 加载现有 PDF 文档
val sourceDocument = PDDocument.load(File(srcPath), password)
LogEx.logDebug(TAG, "sourceDocument open")
// 创建新的 PDF 文档
val newDocument = PDDocument()
// 遍历指定的页面范围
splitIndex.forEach { index ->
val page = sourceDocument.getPage(index)
newDocument.addPage(page)
}
// 保存新的 PDF 文档
newDocument.save(newPath)
newDocument.close()
sourceDocument.close()
} catch (e: Exception) {
LogEx.logDebug(TAG, "splitPdf error")
finishAction.invoke(null)
return@Thread
}
finishAction.invoke(File(newPath))
}.start()
fun createAvoidDupNamePath(path: String): String {
val file = File(path)
var newName = file.name.split(".")[0]
//aaaa_1.pdf
if (isUnderscoreNumberSuffix(newName)) {
val nameSplit = newName.split("_")
val number = nameSplit[1].toInt() + 1
newName = "${nameSplit[0]}_$number"
} else {
newName = "${newName}_1"
}
val newFile = File(file.parentFile, "$newName.pdf")
if (!newFile.exists()) {
newFile.createNewFile()
}
return newFile.absolutePath
}
private fun isUnderscoreNumberSuffix(input: String): Boolean {
val pattern = "_\\d+$".toRegex()
return pattern.matches(input)
}
private fun createAppDocumentDir(): File {
val appName = context.resources.getString(R.string.app_name)
val appDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), appName)
if (!appDir.exists()) {
appDir.mkdirs()
}
return appDir
}
fun createNewPdfPath(name: String): String {
val appDir = createAppDocumentDir()
val mergeFile = File(appDir, "$name.pdf")
mergeFile.createNewFile()
LogEx.logDebug(TAG, "mergeFile ${mergeFile.absolutePath}")
return mergeFile.absolutePath
}
fun mergePdf(mergePath: String, finishAction: (success: Boolean) -> Unit) = Thread {
// var isSuccess: Boolean = false
// try {
// val mergerUtility = PDFMergerUtility()
// mergerUtility.destinationFileName = mergePath
//
// //解密
// PdfMergeActivity.mergePdfList.filter { it.state == 1 }.forEach {
// PdfBoxUtils.clearPassword(it.path, it.password)
// }
//
// LogEx.logDebug(TAG, "mergePdf ${mergePdfList.size}")
// PdfMergeActivity.mergePdfList.forEach { documentBean ->
// LogEx.logDebug(TAG, "mergePdf item= ${documentBean.path} ${documentBean.state}")
//
// //带密码 mergerUtility.addSource(inputStream) 不行
// mergerUtility.addSource(File(documentBean.path))
//
//// if (documentBean.state == 0) {
//// mergerUtility.addSource(File(documentBean.path))
//// } else {
//// LogEx.logDebug(TAG, "mergePdf password=${documentBean.password}")
//// try {
//// val pdfDocument = PDDocument.load(File(documentBean.path), documentBean.password)
//// LogEx.logDebug(TAG, "mergePdf pdfDocument ${pdfDocument.numberOfPages}")
//// val byteArrayOutputStream = ByteArrayOutputStream()
//// pdfDocument.save(byteArrayOutputStream)
//// LogEx.logDebug(TAG, "mergePdf byteArrayOutputStream ${byteArrayOutputStream.size()}")
//// pdfDocument.close()
//// val inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray())
//// LogEx.logDebug(TAG, "mergePdf inputStream")
//// mergerUtility.addSource(inputStream)
//// } catch (e: Exception) {
//// LogEx.logDebug(TAG, "mergePdf Exception ${e.printStackTrace()}")
//// }
//// LogEx.logDebug(TAG, "mergePdf inputStream")
//// }
// }
// mergerUtility.mergeDocuments(null)
//
// //重新加密
// PdfMergeActivity.mergePdfList.filter { it.state == 1 }.forEach {
// val flag = PdfBoxUtils.setPassword(it.path, it.password, it.password)
// LogEx.logDebug(TAG, "重新加密 flag=$flag ${it.path} ${it.password}")
// }
//
// mergePdfList.clear()
// LogEx.logDebug(TAG, "mergePdf finish")
// isSuccess = true
// } catch (e: Exception) {
//
// }
//
//
// finishAction.invoke(isSuccess)
}.start()
}
\ No newline at end of file
package com.base.pdfreader2.ui.pdf
import com.base.pdfreader2.bean.PdfPageBean
interface PdfView {
fun initPdfPageRv(items: List<PdfPageBean>)
fun jumpPage(pageIndex: Int) = Unit
fun jumpSplit() = Unit
}
\ No newline at end of file
package com.base.pdfreader2.ui.view package com.base.pdfreader2.ui.view
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import androidx.core.content.FileProvider
import com.base.pdfreader2.R import com.base.pdfreader2.R
import com.base.pdfreader2.bean.DocumentBean import com.base.pdfreader2.bean.DocumentBean
import com.base.pdfreader2.databinding.DialogPdfHomeMoreBinding import com.base.pdfreader2.databinding.DialogPdfHomeMoreBinding
import com.base.pdfreader2.databinding.DialogPdfMoreBinding
import com.base.pdfreader2.ui.main.DocumentFragment import com.base.pdfreader2.ui.main.DocumentFragment
import com.base.pdfreader2.ui.main.DocumentPresenter import com.base.pdfreader2.ui.main.DocumentPresenter
import com.base.pdfreader2.ui.pdf.PdfView
import com.base.pdfreader2.ui.view.DialogView.showDeleteDialog import com.base.pdfreader2.ui.view.DialogView.showDeleteDialog
import com.base.pdfreader2.ui.view.DocumentDialog.showDocumentDetail import com.base.pdfreader2.ui.view.DocumentDialog.showDocumentDetail
import com.base.pdfreader2.ui.view.NameDialog.showDocumentRenameDialog import com.base.pdfreader2.ui.view.NameDialog.showDocumentRenameDialog
...@@ -16,6 +21,7 @@ import com.base.pdfreader2.ui.view.PwdDialog.showPdfPwdDialog ...@@ -16,6 +21,7 @@ import com.base.pdfreader2.ui.view.PwdDialog.showPdfPwdDialog
import com.base.pdfreader2.utils.IntentShareUtils import com.base.pdfreader2.utils.IntentShareUtils
import com.base.pdfreader2.utils.KotlinExt.toFormatSize import com.base.pdfreader2.utils.KotlinExt.toFormatSize
import com.base.pdfreader2.utils.KotlinExt.toFormatTime import com.base.pdfreader2.utils.KotlinExt.toFormatTime
import com.base.pdfreader2.utils.LogEx
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import java.io.File import java.io.File
...@@ -115,162 +121,48 @@ object PdfDialog { ...@@ -115,162 +121,48 @@ object PdfDialog {
return dialog return dialog
} }
// fun Activity.showPdfMoreDialog( fun Activity.showPdfMoreDialog(
// pdfView: PdfView, pdfView: PdfView,
// pageNumber: Int, pageNumber: Int,
// pafPath: String, pafPath: String,
// ) { ) {
// val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog) val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
// val binding = DialogPdfMoreBinding.inflate(LayoutInflater.from(this)) val binding = DialogPdfMoreBinding.inflate(LayoutInflater.from(this))
// dialog.setContentView(binding.root) dialog.setContentView(binding.root)
// dialog.setCanceledOnTouchOutside(false) dialog.setCanceledOnTouchOutside(false)
//
// dialog.show() dialog.show()
//
// val parentView = binding.root.parent as View val parentView = binding.root.parent as View
// val behavior = BottomSheetBehavior.from(parentView) val behavior = BottomSheetBehavior.from(parentView)
// //展开 //展开
// behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.state = BottomSheetBehavior.STATE_EXPANDED
//
// binding.llJump.setOnClickListener { binding.llJump.setOnClickListener {
// showJumpPageNumberDialog(pageNumber) { pageIndex -> // showJumpPageNumberDialog(pageNumber) { pageIndex ->
// dialog.dismiss() // dialog.dismiss()
// pdfView.jumpPage(pageIndex) // pdfView.jumpPage(pageIndex)
// } // }
// } }
// binding.llSplit.setOnClickListener { binding.llSplit.setOnClickListener {
// dialog.dismiss() dialog.dismiss()
// pdfView.jumpSplit() pdfView.jumpSplit()
// } }
// binding.llDetail.setOnClickListener { binding.llDetail.setOnClickListener {
// showDocumentDetail(pafPath) showDocumentDetail(pafPath)
// } }
// binding.llShare.setOnClickListener { binding.llShare.setOnClickListener {
// dialog.dismiss() dialog.dismiss()
// runCatching { runCatching {
// val pkg = this.packageName val pkg = this.packageName
// LogEx.logDebug("showPdfMoreDialog", "pkg=$pkg") LogEx.logDebug("showPdfMoreDialog", "pkg=$pkg")
// val uri = FileProvider.getUriForFile( val uri = FileProvider.getUriForFile(
// this, this.packageName + ".provider", File(pafPath) this, this.packageName + ".provider", File(pafPath)
// ) )
// startActivity(Intent.createChooser(IntentShareUtils.sharePdfIntent(uri), "Share PDF")) startActivity(Intent.createChooser(IntentShareUtils.sharePdfIntent(uri), "Share PDF"))
// } }
// } }
// binding.llPrint.setOnClickListener {
// val uri = FileProvider.getUriForFile( }
// this, this.packageName + ".provider", File(pafPath)
// )
// startActivity(Intent.createChooser(IntentShareUtils.sharePdfPrintIntent(uri), "Print PDF"))
// }
//
// }
// @SuppressLint("SetTextI18n")
// fun Context.showPdfPwdDialog(
// state: Int,
// path: String = "",
// uri: String? = null,
// firstDialog: Dialog? = null,
// isCheckPwd: Boolean = false,
// verificationAction: ((pwd: String) -> Unit)? = null,
// encryptionAction: (() -> Unit)? = null,
// cancelAction: (() -> Unit)? = null,
// ) {
// val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
// val binding = DialogPdfPasswordBinding.inflate(LayoutInflater.from(this))
// dialog.setContentView(binding.root)
// dialog.setCanceledOnTouchOutside(false)
//
// val window = dialog.window
// window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
//
// dialog.show()
//
// val parentView = binding.root.parent as View
// val behavior = BottomSheetBehavior.from(parentView)
// //展开
// behavior.state = BottomSheetBehavior.STATE_EXPANDED
//
// if (!isCheckPwd) {
// if (state == 1) {
// binding.tvTittle.text = getString(R.string.delete_password)
// binding.tvTip.text = getString(R.string.delete_password_the_file_is_not_password_protected)
// }
// if (state == 0) {
// binding.tvTittle.text = getString(R.string.set_password)
// binding.tvTip.text = getString(R.string.set_password_protection_pdf)
//
// }
// } else {
// binding.tvTittle.text = getString(R.string.input_password)
// val file = File(path)
// binding.tvTip.text = getString(R.string.password_protected, file.name)
// binding.tvInputTip.visibility = View.VISIBLE
// }
//
// binding.edit.requestFocus()
// binding.edit.addTextChangedListener {
// binding.tvConfirm.isEnabled = it.toString().isNotEmpty()
// binding.tvErrorTip.visibility = View.GONE
// }
//
// binding.tvCancel.setOnClickListener {
// dialog.dismiss()
// cancelAction?.invoke()
// }
// binding.tvConfirm.setOnClickListener {
//
// val pwd = binding.edit.text.toString()
//
// if (!isCheckPwd) {
//
// //加锁逻辑
// if (state == 0) {
// PdfBoxUtils.setPassword(path, pwd, pwd)
// toast("Success Encryption")
// encryptionAction?.invoke()
// dialog.dismiss()
// firstDialog?.dismiss()
// }
// //解锁逻辑
// if (state == 1) {
// val result = PdfBoxUtils.checkPwd(path, pwd, uri)
// LogEx.logDebug("checkPwd", "result=$result")
// if (result) {
// PdfBoxUtils.clearPassword(path, pwd)
// toast("clear Encryption")
// encryptionAction?.invoke()
// dialog.dismiss()
// firstDialog?.dismiss()
// } else {
// binding.tvErrorTip.visibility = View.VISIBLE
// }
// }
// } else {
// //验证密码逻辑
// val result = PdfBoxUtils.checkPwd(path, pwd, uri)
// if (!result) {
// binding.tvErrorTip.visibility = View.VISIBLE
// return@setOnClickListener
// }
// dialog.dismiss()
// firstDialog?.dismiss()
// verificationAction?.invoke(pwd)
// }
//
// }
// binding.ivEye.setOnClickListener {
//
// if (binding.edit.transformationMethod == null) {
// // 隐藏密码
// binding.edit.transformationMethod = PasswordTransformationMethod()
// binding.ivEye.setImageResource(R.mipmap.weishuru)
// } else {
// // 显示密码
// binding.edit.transformationMethod = null
// binding.ivEye.setImageResource(R.mipmap.yishuru)
// }
// }
//
// }
} }
\ No newline at end of file
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package com.base.pdfreader2.ui.view
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.cardview.widget.CardView
import androidx.core.view.ViewCompat
import com.base.pdfreader2.R
import com.base.pdfreader2.utils.LogEx
import kotlin.math.max
import kotlin.math.roundToInt
/**
* A nicer, redesigned and vertical SeekBar
* copy from:
* https://github.com/lukelorusso/VerticalSeekBar
*
*/
class VerticalSeekBar : FrameLayout {
private val TAG = "VerticalSeekBar"
constructor(context: Context) : super(context) {
LogEx.logDebug(TAG, "init1")
initAttributes(context, null)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
LogEx.logDebug(TAG, "init2")
initAttributes(context, attrs)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
LogEx.logDebug(TAG, "init3")
initAttributes(context, attrs)
}
companion object {
private const val DEFAULT_MAX_VALUE = 100
private const val DEFAULT_PROGRESS = 50
private const val DEFAULT_DRAWABLE_BACKGROUND: String = "#00000000"
private const val DEFAULT_DRAWABLE_PROGRESS_START: String = "#00000000"
private const val DEFAULT_DRAWABLE_PROGRESS_END: String = "#00000000"
}
enum class Placeholder {
OUTSIDE,
INSIDE,
MIDDLE
}
private var onProgressChangeListener: ((Int) -> Unit)? = null
private var onPressListener: ((Int) -> Unit)? = null
private var onReleaseListener: ((Int) -> Unit)? = null
var clickToSetProgress = true
set(value) {
field = value
applyAttributes()
}
var barCornerRadius: Int = 0
set(value) {
field = value
applyAttributes()
}
var barBackgroundDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var barBackgroundStartColor: Int = Color.parseColor(DEFAULT_DRAWABLE_BACKGROUND)
set(value) {
field = value
barBackgroundDrawable = null
applyAttributes()
}
var barBackgroundEndColor: Int = Color.parseColor(DEFAULT_DRAWABLE_BACKGROUND)
set(value) {
field = value
barBackgroundDrawable = null
applyAttributes()
}
var barProgressDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var barProgressStartColor: Int = Color.parseColor(DEFAULT_DRAWABLE_PROGRESS_START)
set(value) {
field = value
barProgressDrawable = null
applyAttributes()
}
var barProgressEndColor: Int = Color.parseColor(DEFAULT_DRAWABLE_PROGRESS_END)
set(value) {
field = value
barProgressDrawable = null
applyAttributes()
}
var barWidth: Int? = null
set(value) {
field = value
applyAttributes()
}
var minLayoutWidth: Int = 0
set(value) {
field = value
applyAttributes()
}
var minLayoutHeight: Int = 0
set(value) {
field = value
applyAttributes()
}
var maxPlaceholderDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var maxPlaceholderPosition = Placeholder.MIDDLE
set(value) {
field = value
applyAttributes()
}
var minPlaceholderDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var minPlaceholderPosition = Placeholder.MIDDLE
set(value) {
field = value
applyAttributes()
}
var showThumb = true
set(value) {
field = value
applyAttributes()
}
var thumbContainerColor: Int = Color.WHITE
set(value) {
field = value
applyAttributes()
}
var thumbContainerCornerRadius: Int = 0
set(value) {
field = value
applyAttributes()
}
var thumbPlaceholderDrawable: Drawable? = null
set(value) {
field = value
applyAttributes()
}
var useThumbToSetProgress = true
set(value) {
field = value
applyAttributes()
}
var maxValue = DEFAULT_MAX_VALUE
set(value) {
val newValue = when {
value < 1 -> 1
else -> value
}
if (progress > newValue) progress = newValue
field = newValue
updateViews()
}
var progress: Int = DEFAULT_PROGRESS
set(value) {
val newValue = when {
value < 0 -> 0
value > maxValue -> maxValue
else -> value
}
if (field != newValue) {
onProgressChangeListener?.invoke(newValue)
}
field = newValue
updateViews()
}
private var yDelta: Int = 0
private var initEnded =
false // if true allows the view to be updated after setting an attribute programmatically
lateinit var container: FrameLayout
lateinit var thumb: FrameLayout
lateinit var barCardView: CardView
lateinit var barBackground: View
lateinit var barProgress: View
lateinit var maxPlaceholder: ImageView
lateinit var minPlaceholder: ImageView
private fun initAttributes(context: Context, attrs: AttributeSet?) {
val view = inflate(context, R.layout.layout_verticalseekbar, this)
container = findViewById(R.id.container)
thumb = findViewById(R.id.thumb)
barCardView = findViewById(R.id.barCardView)
barBackground = findViewById(R.id.barBackground)
barProgress = findViewById(R.id.barProgress)
maxPlaceholder = findViewById(R.id.maxPlaceholder)
minPlaceholder = findViewById(R.id.minPlaceholder)
if (attrs != null) {
val attributes =
context.obtainStyledAttributes(attrs, R.styleable.VerticalSeekBar, 0, 0)
LogEx.logDebug(TAG, "attributes=$attributes")
try {
clickToSetProgress =
attributes.getBoolean(
R.styleable.VerticalSeekBar_vsb_click_to_set_progress,
clickToSetProgress
)
barCornerRadius = attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_vsb_bar_corner_radius,
barCornerRadius
)
barBackgroundStartColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_background_gradient_start,
barBackgroundStartColor
)
barBackgroundEndColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_background_gradient_end,
barBackgroundEndColor
)
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_bar_background)?.also {
barBackgroundDrawable = it
}
barProgressStartColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_progress_gradient_start,
barProgressStartColor
)
barProgressEndColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_bar_progress_gradient_end,
barProgressEndColor
)
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_bar_progress).also {
barProgressDrawable = it
}
barWidth = attributes.getDimensionPixelSize(
R.styleable.VerticalSeekBar_vsb_bar_width,
barWidth ?: container.layoutParams.width
)
attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_android_layout_width,
minLayoutWidth
).also {
container.layoutParams.width =
if (it != -1 && it < minLayoutWidth) minLayoutWidth // wrap_content
else it
}
attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_android_layout_height,
minLayoutHeight
).also {
container.layoutParams.height =
if (it != -1 && it < minLayoutHeight) minLayoutHeight // wrap_content
else it
}
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_max_placeholder_src).also {
maxPlaceholderDrawable = it
}
maxPlaceholderPosition = Placeholder.values()[attributes.getInt(
R.styleable.VerticalSeekBar_vsb_max_placeholder_position,
maxPlaceholderPosition.ordinal
)]
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_min_placeholder_src).also {
minPlaceholderDrawable = it
}
minPlaceholderPosition = Placeholder.values()[attributes.getInt(
R.styleable.VerticalSeekBar_vsb_min_placeholder_position,
minPlaceholderPosition.ordinal
)]
showThumb =
attributes.getBoolean(R.styleable.VerticalSeekBar_vsb_show_thumb, showThumb)
thumbContainerColor =
attributes.getColor(
R.styleable.VerticalSeekBar_vsb_thumb_container_tint,
thumbContainerColor
)
thumbContainerCornerRadius = attributes.getLayoutDimension(
R.styleable.VerticalSeekBar_vsb_thumb_container_corner_radius,
thumbContainerCornerRadius
)
attributes.getDrawable(R.styleable.VerticalSeekBar_vsb_thumb_placeholder_src).also {
thumbPlaceholderDrawable = it
}
attributes.getInt(R.styleable.VerticalSeekBar_vsb_max_value, maxValue).also {
maxValue = it
}
attributes.getInt(R.styleable.VerticalSeekBar_vsb_progress, progress).also {
progress = it
}
useThumbToSetProgress =
attributes.getBoolean(
R.styleable.VerticalSeekBar_vsb_use_thumb_to_set_progress,
useThumbToSetProgress
)
} finally {
attributes.recycle()
}
}
initEnded = true
applyAttributes()
}
fun setOnProgressChangeListener(listener: ((Int) -> Unit)?) {
this.onProgressChangeListener = listener
}
fun setOnPressListener(listener: ((Int) -> Unit)?) {
this.onPressListener = listener
}
fun setOnReleaseListener(listener: ((Int) -> Unit)?) {
this.onReleaseListener = listener
}
//region PROTECTED METHODS
protected fun Context.dpToPixel(dp: Float): Float =
dp * (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
protected fun Context.pixelToDp(px: Float): Float =
px / (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
//endregion
@SuppressLint("ClickableViewAccessibility")
private fun applyAttributes() {
if (initEnded) {
initEnded = false // will be released at the end
var thumbCardView: CardView? = null // nullable for customization
try {
thumbCardView = thumb.findViewById(R.id.thumbCardView)
} catch (ignored: NoSuchFieldError) {
}
var thumbPlaceholder: ImageView? = null // nullable for customization
try {
thumbPlaceholder = findViewById<FrameLayout>(R.id.thumb).findViewById(R.id.thumbPlaceholder)
} catch (ignored: NoSuchFieldError) {
}
// Customizing drawableCardView
barCardView.layoutParams.width = barWidth ?: 0
// Customizing drawableBackground
if (barBackgroundDrawable == null) barBackgroundDrawable = GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(barBackgroundStartColor, barBackgroundEndColor)
).apply { cornerRadius = 0f }
barBackground.background = barBackgroundDrawable
// Customizing drawableProgress
if (barProgressDrawable == null) barProgressDrawable = GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(barProgressStartColor, barProgressEndColor)
).apply { cornerRadius = 0f }
barProgress.background = barProgressDrawable
// Applying card corner radius
barCardView.radius = barCornerRadius.toFloat()
thumbCardView?.radius = thumbContainerCornerRadius.toFloat()
// Applying custom placeholders
maxPlaceholder.setImageDrawable(maxPlaceholderDrawable) // can also be null
minPlaceholder.setImageDrawable(minPlaceholderDrawable) // can also be null
// Let's shape the thumb
val thumbMeasureIncrease =
if (thumbCardView != null) (ViewCompat.getElevation(thumbCardView)
+ context.dpToPixel(1F)).roundToInt()
else 0
if (showThumb) {
thumbPlaceholderDrawable?.also { thumbPlaceholder?.setImageDrawable(it) } // CANNOT be null
thumb.visibility = View.VISIBLE
val states = arrayOf(
intArrayOf(android.R.attr.state_enabled), // enabled
intArrayOf(-android.R.attr.state_enabled), // disabled
intArrayOf(-android.R.attr.state_checked), // unchecked
intArrayOf(android.R.attr.state_pressed) // pressed
)
val colors = arrayOf(
thumbContainerColor,
thumbContainerColor,
thumbContainerColor,
thumbContainerColor
).toIntArray()
if (thumbCardView != null)
ViewCompat.setBackgroundTintList(thumbCardView, ColorStateList(states, colors))
thumb.measure(0, 0)
thumb.layoutParams = (thumb.layoutParams as LayoutParams).apply {
width = thumb.measuredWidth + thumbMeasureIncrease
height = thumb.measuredHeight + thumbMeasureIncrease
thumbCardView?.layoutParams =
(thumbCardView?.layoutParams as LayoutParams).apply {
topMargin = thumbMeasureIncrease / 2
}
}
} else thumb.visibility = View.GONE
// Adding some margin to drawableCardView, maxPlaceholder and minPlaceholder
val maxPlaceholderLayoutParams = (maxPlaceholder.layoutParams as LayoutParams)
val minPlaceholderLayoutParams = (minPlaceholder.layoutParams as LayoutParams)
barCardView.layoutParams = (barCardView.layoutParams as LayoutParams).apply {
val thumbHalfHeight =
if (showThumb) thumb.measuredHeight / 2
else 0
val maxPlaceholderHalfHeight = (maxPlaceholder.drawable?.intrinsicHeight ?: 0) / 2
when (maxPlaceholderPosition) {
Placeholder.INSIDE -> {
topMargin = thumbHalfHeight
maxPlaceholderLayoutParams.topMargin = topMargin
}
Placeholder.OUTSIDE -> {
topMargin = maxPlaceholder.drawable.intrinsicHeight +
if (thumbHalfHeight > maxPlaceholder.drawable.intrinsicHeight)
thumbHalfHeight - maxPlaceholder.drawable.intrinsicHeight
else 0
maxPlaceholderLayoutParams.topMargin =
topMargin - maxPlaceholder.drawable.intrinsicHeight
}
else -> {
topMargin = max(thumbHalfHeight, maxPlaceholderHalfHeight)
maxPlaceholderLayoutParams.topMargin = topMargin - maxPlaceholderHalfHeight
}
}
maxPlaceholderLayoutParams.bottomMargin = maxPlaceholderLayoutParams.topMargin
maxPlaceholder.layoutParams = maxPlaceholderLayoutParams
val minPlaceholderHalfHeight = (minPlaceholder.drawable?.intrinsicHeight ?: 0) / 2
when (minPlaceholderPosition) {
Placeholder.INSIDE -> {
bottomMargin = thumbHalfHeight
minPlaceholderLayoutParams.bottomMargin = bottomMargin
}
Placeholder.OUTSIDE -> {
bottomMargin = minPlaceholder.drawable.intrinsicHeight +
if (thumbHalfHeight > minPlaceholder.drawable.intrinsicHeight)
thumbHalfHeight - minPlaceholder.drawable.intrinsicHeight
else 0
minPlaceholderLayoutParams.bottomMargin =
bottomMargin - minPlaceholder.drawable.intrinsicHeight
}
else -> {
bottomMargin = max(thumbHalfHeight, minPlaceholderHalfHeight)
minPlaceholderLayoutParams.bottomMargin =
bottomMargin - minPlaceholderHalfHeight
}
}
bottomMargin += thumbMeasureIncrease
minPlaceholderLayoutParams.bottomMargin += thumbMeasureIncrease
minPlaceholderLayoutParams.topMargin = maxPlaceholderLayoutParams.bottomMargin
minPlaceholder.layoutParams = minPlaceholderLayoutParams
}
// here we intercept the click on the thumb
if (showThumb && useThumbToSetProgress) thumb.setOnTouchListener { thumb, event ->
val rawY = event.rawY.roundToInt()
when (event.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_DOWN -> { // here we get the max top y coordinate (yDelta)
yDelta = rawY +
(barCardView.layoutParams as LayoutParams).topMargin -
(thumb.layoutParams as LayoutParams).topMargin -
thumb.measuredHeight / 2
onPressListener?.invoke(progress)
}
MotionEvent.ACTION_MOVE -> {
val positionY = rawY - yDelta // here we calculate the displacement
val fillHeight = barCardView.measuredHeight
when { // here we update progress
positionY in 1 until fillHeight -> {
val newValue =
maxValue - (positionY.toFloat() * maxValue / fillHeight)
progress = newValue.roundToInt()
}
positionY <= 0 -> progress = maxValue
positionY >= fillHeight -> progress = 0
}
}
MotionEvent.ACTION_UP -> onReleaseListener?.invoke(progress)
}
true
} else thumb.setOnTouchListener(null)
// here we intercept the click on the bar
if (clickToSetProgress) barCardView.setOnTouchListener { bar, event ->
val positionY = event.y.roundToInt()
val action = {
val fillHeight = bar.measuredHeight
when { // here we update progress
positionY in 1 until fillHeight -> {
val newValue = maxValue - (positionY.toFloat() * maxValue / fillHeight)
progress = newValue.roundToInt()
}
positionY <= 0 -> progress = maxValue
positionY >= fillHeight -> progress = 0
}
}
when (event.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_DOWN -> {
action.invoke()
onPressListener?.invoke(progress)
}
MotionEvent.ACTION_MOVE -> if (useThumbToSetProgress) action.invoke()
MotionEvent.ACTION_UP -> onReleaseListener?.invoke(progress)
}
true
} else barCardView.setOnTouchListener(null)
initEnded = true
updateViews()
}
}
/**
* Inside here the views are repositioned based on the new value
*/
private fun updateViews() {
if (initEnded) post {
val barCardViewLayoutParams = barCardView.layoutParams as LayoutParams
val fillHeight =
height - barCardViewLayoutParams.topMargin - barCardViewLayoutParams.bottomMargin
val marginByProgress = fillHeight - (progress * fillHeight / maxValue)
thumb.layoutParams = (thumb.layoutParams as LayoutParams).apply {
topMargin = marginByProgress
val thumbHalfHeight = if (showThumb) thumb.measuredHeight / 2 else 0
if (barCardViewLayoutParams.topMargin > thumbHalfHeight) {
val displacement = barCardViewLayoutParams.topMargin - thumbHalfHeight
topMargin += displacement
}
}
barProgress.translationY =
(barBackground.height * (maxValue - progress) / maxValue).toFloat()
invalidate()
}
}
}
package com.base.pdfreader2.ui.view
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import com.airbnb.lottie.LottieAnimationView
class XmlLottieAnimationView : LottieAnimationView {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun draw(canvas: Canvas) {
try {
super.draw(canvas)
} catch (e: Exception) {
}
}
override fun playAnimation() {
super.playAnimation()
}
}
\ No newline at end of file
package com.base.pdfreader2.utils
import android.annotation.SuppressLint
import android.content.Context
import android.content.Context.INPUT_METHOD_SERVICE
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
object KeyBoardUtils {
@SuppressLint("ServiceCast")
fun Context.hideKeyboard(editText: EditText) {
editText.clearFocus()
val imm = this.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(editText.windowToken, 0)
}
@SuppressLint("ServiceCast")
fun Context.showKeyBoard(editText: EditText) {
editText.requestFocus()
val imm = this.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager?
imm?.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}
}
\ No newline at end of file
...@@ -41,9 +41,14 @@ object LanguageUtils { ...@@ -41,9 +41,14 @@ object LanguageUtils {
return supportLanguage.contains(getSystemLanguage()) return supportLanguage.contains(getSystemLanguage())
} }
fun changeAppLanguage(context: Context,language:String) { fun changeAppLanguage(context: Context,languageCountry:String) {
val config = context.resources.configuration val config = context.resources.configuration
val locale = Locale(language) val lc = languageCountry.split("_")
val locale = if (lc.size == 2) {
Locale(lc[0], lc[1])
} else {
Locale(lc[0])
}
//Android 7.0以上的方法 //Android 7.0以上的方法
config.setLocale(locale) config.setLocale(locale)
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#00B8DE"/>
<corners android:radius="4dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp" />
<solid android:color="#54585B" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#9699A2" />
<corners android:radius="4dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#B3000000" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_stoke_00bbde_5" android:state_selected="true"/>
<item android:drawable="@drawable/bg_stoke_cfcfcf_5" android:state_selected="false"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/bg_00b8de_4"/>
<item android:state_selected="false" android:drawable="@drawable/bg_9699a2_4"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#00B8DE" />
<corners android:radius="5dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#CFCFCF" />
<corners android:radius="5dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/v_animator_bottom"
app:layout_constraintTop_toBottomOf="@id/v_animator_top">
<com.artifex.mupdfdemo.MuPDFReaderView
android:id="@+id/mupdf_reader_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.artifex.mupdfdemo.MuPDFReaderView>
<com.base.pdfreader2.ui.view.VerticalSeekBar
android:id="@+id/vertical_seekbar"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginEnd="10dp"
android:visibility="gone"
app:vsb_bar_background="@color/transparent"
app:vsb_bar_progress="@color/transparent"
app:vsb_show_thumb="true" />
</FrameLayout>
<ViewAnimator
android:id="@+id/v_animator_top"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="60dp"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/tv_pdf_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="15dp"
android:src="@mipmap/fanhui_b"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_pdf_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/iv_xuanzhuan"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText"
tools:text="DEMO.pdf" />
<ImageView
android:id="@+id/iv_xuanzhuan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@mipmap/hengping"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_search"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@mipmap/h_sousuo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_more"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_wancheng"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@mipmap/wancheng"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/iv_more"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/iv_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@mipmap/x_genduo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<EditText
android:id="@+id/edit_search"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_f8f9fe_10"
android:hint="input..."
android:paddingHorizontal="18dp"
android:singleLine="true"
android:textColor="@color/black"
android:textColorHint="#B8B9BD"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_search"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="Autofill,HardcodedText,TextFields" />
<TextView
android:id="@+id/tv_btn_save"
android:layout_width="90dp"
android:layout_height="36dp"
android:background="@drawable/bg_00b8de_10"
android:gravity="center"
android:text="@string/save"
android:textColor="@color/white"
android:textSize="16sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/iv_more"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ViewAnimator>
<TextView
android:id="@+id/tv_pageCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="28dp"
android:background="@drawable/bg_54585b_5"
android:includeFontPadding="false"
android:paddingHorizontal="2dp"
android:paddingVertical="2dp"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_animator_top"
tools:text="1/3" />
<ImageView
android:id="@+id/iv_bianji"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="35dp"
android:layout_marginBottom="108dp"
android:src="@mipmap/bianji"
app:layout_constraintBottom_toBottomOf="@id/v_animator_bottom"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ContentDescription" />
<ViewAnimator
android:id="@+id/v_animator_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/white"
app:layout_constraintBottom_toTopOf="@id/fl_ad">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="UselessParent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_operation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingVertical="8dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/v_animator_bottom">
<LinearLayout
android:id="@+id/ll_highlight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_glide_line"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/highlight"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="6dp"
android:text="@string/highlight"
android:textColor="#232323"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_glide_line"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_strikethrough"
app:layout_constraintStart_toEndOf="@id/ll_highlight"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/glideline"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="6dp"
android:text="@string/glide_line"
android:textColor="#232323"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_strikethrough"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_painting_brush"
app:layout_constraintStart_toEndOf="@id/ll_glide_line"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/strike"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="6dp"
android:text="@string/strikethrough"
android:textColor="#232323"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_painting_brush"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ll_strikethrough"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/painting"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="6dp"
android:text="@string/painting_brush"
android:textColor="#232323"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_pager"
android:layout_width="match_parent"
android:layout_height="88dp"
android:orientation="horizontal"
android:paddingHorizontal="4dp"
android:paddingTop="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
tools:listitem="@layout/item_pdf_pager" />
</LinearLayout>
</ViewAnimator>
<FrameLayout
android:id="@+id/fl_ad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/zhanweitu2"
tools:ignore="ContentDescription" />
</FrameLayout>
<FrameLayout
android:id="@+id/fl_guide_gesture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_b3000000_10"
tools:ignore="UselessParent">
<com.base.pdfreader2.ui.view.XmlLottieAnimationView
android:id="@+id/lottie"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/enlarge" />
</FrameLayout>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_f1f1f1_tlr25"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl"
android:layout_width="match_parent"
android:layout_height="65dp"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="@string/more"
android:textColor="#333333"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/iv_bookmark"
android:layout_width="24dp"
android:layout_height="32dp"
android:layout_marginEnd="27dp"
android:src="@mipmap/h_soucang_n"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl">
<LinearLayout
android:id="@+id/ll_merge"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/merge"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="13dp"
android:layout_weight="1"
android:ellipsize="end"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/merge_pdf"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_split"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/split"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="13dp"
android:layout_weight="1"
android:ellipsize="end"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/split_pdf"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_jump"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/jump"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="13dp"
android:layout_weight="1"
android:ellipsize="end"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/jump_to_the_specified_page"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_detail"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/particulars"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="13dp"
android:layout_weight="1"
android:ellipsize="end"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/detail"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_share"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="13dp"
android:src="@mipmap/share"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="13dp"
android:layout_weight="1"
android:ellipsize="end"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/share"
android:textColor="#333333"
android:textSize="16sp"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fl_border"
android:layout_width="53dp"
android:layout_height="75dp"
android:layout_margin="4dp"
android:background="@drawable/bg_selector_pager_border">
<ImageView
android:id="@+id/iv_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
android:importantForAccessibility="no"
android:scaleType="fitXY" />
<TextView
android:id="@+id/tv_pager_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="4dp"
android:background="@drawable/bg_selector_pager_text"
android:padding="1dp"
android:text="1"
android:textSize="8sp"
tools:ignore="HardcodedText,SmallSp" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fl_border"
android:layout_width="103dp"
android:layout_height="145dp"
android:layout_marginHorizontal="5dp"
android:layout_marginVertical="5dp"
android:background="@drawable/bg_selector_pager_border">
<ImageView
android:id="@+id/iv_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
android:importantForAccessibility="no"
android:scaleType="centerCrop" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|top"
android:layout_margin="8dp"
android:src="@drawable/bg_selector_select"
tools:ignore="ContentDescription" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/transparent">
<androidx.cardview.widget.CardView
android:id="@+id/barCardView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp">
<View
android:id="@+id/barBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" />
<View
android:id="@+id/barProgress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" />
</androidx.cardview.widget.CardView>
<FrameLayout
android:id="@+id/maxPlaceholderLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@color/transparent">
<ImageView
android:id="@+id/maxPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@null" />
</FrameLayout>
<FrameLayout
android:id="@+id/minPlaceholderLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:background="@color/transparent">
<ImageView
android:id="@+id/minPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="@null" />
</FrameLayout>
<FrameLayout
android:id="@+id/thumb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/thumbCardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:cardElevation="0dp">
<ImageView
android:id="@+id/thumbPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null" />
</androidx.cardview.widget.CardView>
</FrameLayout>
</FrameLayout>
{"v":"5.9.4","fr":25,"ip":0,"op":25,"w":186,"h":186,"nm":"hand_zoom","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[21.5,104.75,0],"to":[2.667,-3.375,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[37.5,84.5,0],"to":[0,0,0],"ti":[2.667,-3.375,0]},{"t":19,"s":[21.5,104.75,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.562,1.341],[-0.781,1.006],[0,0],[1.004,0.782],[0,0],[0.781,-1.006],[0,0],[1.004,0.783],[0,-2.124],[0,0],[-1.45,0.224],[0,0]],"o":[[-1.004,-0.894],[0,0],[0.892,-1.006],[0,0],[-1.004,-0.894],[0,0],[-0.892,1.006],[-1.562,-1.341],[0,0],[0,1.453],[0,0],[2.008,-0.559]],"v":[[1.282,9.6],[0.947,6.246],[13.441,-8.733],[13.106,-12.086],[9.091,-15.44],[5.744,-15.104],[-6.749,-0.125],[-10.096,0.21],[-14,2.11],[-13.888,13.624],[-11.1,15.971],[0.167,13.959]],"c":true},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Group 2","np":0,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":25,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[80.375,27.25,0],"to":[-2.833,4.083,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[63.375,51.75,0],"to":[0,0,0],"ti":[-2.833,4.083,0]},{"t":19,"s":[80.375,27.25,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.122,-0.892],[0,0],[-0.786,1.003],[0,0],[-1.01,-0.892],[0,2.006],[0,0],[1.459,-0.334],[0,0],[-1.571,-1.337],[0.898,-1.003],[0,0]],"o":[[0,0],[1.01,0.78],[0,0],[0.786,-1.003],[1.571,1.226],[0,0],[0,-1.449],[0,0],[-2.02,0.446],[1.01,0.78],[0,0],[-0.786,0.78]],"v":[[-13.045,12.256],[-8.893,15.488],[-5.526,15.154],[6.706,-0.115],[10.072,-0.449],[14,-2.344],[13.663,-13.711],[10.746,-15.94],[-0.588,-13.711],[-1.598,-9.476],[-1.262,-6.133],[-13.494,9.135]],"c":true},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Group 2","np":0,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":25,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"hand_zoom contornos","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[93,106,0],"ix":2,"l":2},"a":{"a":0,"k":[180,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-11.984],[0,0],[0,0]],"o":[[0,0],[0,-11.984],[0,0],[0,0],[0,0]],"v":[[-7.49,33.438],[-7.49,-21.454],[7.49,-21.454],[7.49,27.003],[7.49,7.828]],"c":false},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[184.917,162.762],"ix":2},"a":{"a":0,"k":[-0.652,28.499],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.167,0.167],"y":[0,0.167]},"t":0,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.167,0.167],"y":[0,0.167]},"t":10,"s":[100,90]},{"t":19,"s":[100,100]}],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[-10]},{"t":19,"s":[0]}],"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Grupo 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.56,-6.271],[0,0]],"o":[[0,0],[6.56,-6.269],[0,0],[0,0]],"v":[[13.938,24.07],[-15.837,-17.801],[3.771,-15.293],[15.836,-5.393]],"c":false},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[178.406,180.584],"ix":2},"a":{"a":0,"k":[16.164,7.49],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,1]},"o":{"x":[0.167,0.167],"y":[0.167,0]},"t":0,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,1]},"o":{"x":[0.167,0.167],"y":[0.167,0]},"t":10,"s":[73,100]},{"t":19,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Grupo 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[226.015,154.753],[226.015,164.781]],"c":false},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Grupo 5","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[211.034,148.761],[211.034,163.094]],"c":false},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Grupo 6","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-18.89,0],[0,0],[0,0],[4.638,0],[0,-4.433],[0,0],[4.639,0],[0,-4.434],[0,0],[4.638,0],[0,-4.433],[0,0]],"o":[[0,0],[24.06,0],[0,0],[0,-4.433],[-4.638,0],[0,0],[0,-4.434],[-4.638,0],[0,0],[0,-4.433],[-4.639,0],[0,0],[0,0]],"v":[[-32.786,23.569],[-3.077,39.531],[27.54,10.283],[32.786,-17.71],[24.917,-25.738],[17.048,-17.71],[17.048,-25.236],[8.548,-33.264],[2.068,-25.236],[2.068,-31.503],[-6.92,-39.531],[-15.908,-31.503],[-15.908,-12.327]],"c":false},"ix":2},"nm":"path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[208.966,173.595],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"transform"}],"nm":"Grupo 7","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":750,"st":0,"ct":1,"bm":0}],"markers":[]}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="VerticalSeekBar">
<attr name="vsb_click_to_set_progress" format="boolean" />
<attr name="vsb_bar_corner_radius" format="dimension" />
<attr name="vsb_bar_width" format="dimension" />
<attr name="vsb_bar_background" format="reference|color" />
<attr name="vsb_bar_background_gradient_start" format="color" />
<attr name="vsb_bar_background_gradient_end" format="color" />
<attr name="vsb_bar_progress" format="reference|color" />
<attr name="vsb_bar_progress_gradient_start" format="color" />
<attr name="vsb_bar_progress_gradient_end" format="color" />
<attr name="vsb_progress" format="integer" />
<attr name="vsb_max_value" format="integer" />
<attr name="vsb_min_placeholder_position" format="enum">
<enum name="outside" value="0"/>
<enum name="inside" value="1"/>
<enum name="middle" value="2"/>
</attr>
<attr name="vsb_min_placeholder_src" format="reference" />
<attr name="vsb_max_placeholder_position" format="enum">
<enum name="outside" value="0"/>
<enum name="inside" value="1"/>
<enum name="middle" value="2"/>
</attr>
<attr name="vsb_max_placeholder_src" format="reference" />
<attr name="vsb_show_thumb" format="boolean" />
<attr name="vsb_thumb_container_corner_radius" format="dimension" />
<attr name="vsb_thumb_container_tint" format="color" />
<attr name="vsb_thumb_placeholder_src" format="integer" />
<attr name="vsb_use_thumb_to_set_progress" format="boolean" />
<attr name="android:layout_width" />
<attr name="android:layout_height" />
</declare-styleable>
</resources>
...@@ -7,4 +7,5 @@ ...@@ -7,4 +7,5 @@
<color name="color_1ea362">#1EA362</color> <color name="color_1ea362">#1EA362</color>
<color name="color_f6b911">#F6B911</color> <color name="color_f6b911">#F6B911</color>
<color name="color_80ffffff" >#80FFFFFF</color> <color name="color_80ffffff" >#80FFFFFF</color>
<color name="transparent">#00000000</color>
</resources> </resources>
\ No newline at end of file
...@@ -2,4 +2,5 @@ ...@@ -2,4 +2,5 @@
plugins { plugins {
alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false alias(libs.plugins.jetbrainsKotlinAndroid) apply false
alias(libs.plugins.androidLibrary) apply false
} }
\ No newline at end of file
...@@ -10,6 +10,7 @@ material = "1.10.0" ...@@ -10,6 +10,7 @@ material = "1.10.0"
activity = "1.8.0" activity = "1.8.0"
constraintlayout = "2.1.4" constraintlayout = "2.1.4"
swiperefreshlayout = "1.1.0" swiperefreshlayout = "1.1.0"
toolsCore = "1.0.0-alpha10"
[libraries] [libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
...@@ -21,8 +22,10 @@ material = { group = "com.google.android.material", name = "material", version.r ...@@ -21,8 +22,10 @@ material = { group = "com.google.android.material", name = "material", version.r
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" } androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
androidx-tools-core = { group = "androidx.privacysandbox.tools", name = "tools-core", version.ref = "toolsCore" }
[plugins] [plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" } androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
...@@ -27,4 +27,5 @@ dependencyResolutionManagement { ...@@ -27,4 +27,5 @@ dependencyResolutionManagement {
rootProject.name = "pdf reader 2" rootProject.name = "pdf reader 2"
include(":app") include(":app")
include(":pdflibrary")
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment