增加页脚配置 (#4724)
* 增加点击屏幕下部分右边下一页,左部分上一页 * 优化 * 增加开启自动翻页 * ... * 修改命名 * ... * ... * ... * 页脚配置 * ... * ...
This commit is contained in:
@@ -97,6 +97,7 @@ object PreferKey {
|
||||
const val preDownloadNum = "preDownloadNum"
|
||||
const val mangaPreDownloadNum = "mangaPreDownloadNum"
|
||||
const val mangaAutoPageSpeed = "mangaAutoPageSpeed"
|
||||
const val mangaFooterConfig = "mangaFooterConfig"
|
||||
const val singlePageScrolling = "singlePageScrolling"
|
||||
const val disableClickScroller = "disableClickScroller"
|
||||
const val autoRefresh = "auto_refresh"
|
||||
|
||||
@@ -643,5 +643,13 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
set(value) {
|
||||
appCtx.putPrefInt(PreferKey.mangaAutoPageSpeed, value)
|
||||
}
|
||||
|
||||
//漫画页脚配置
|
||||
var mangaFooterConfig
|
||||
get() = appCtx.getPrefString(PreferKey.mangaFooterConfig, "")
|
||||
set(value) {
|
||||
appCtx.putPrefString(PreferKey.mangaFooterConfig, value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.bumptech.glide.util.FixedPreloadSizeProvider
|
||||
import io.legado.app.BuildConfig
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.VMBaseActivity
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.data.entities.BookChapter
|
||||
import io.legado.app.data.entities.BookProgress
|
||||
@@ -43,16 +44,22 @@ import io.legado.app.model.recyclerView.ReaderLoading
|
||||
import io.legado.app.receiver.NetworkChangedListener
|
||||
import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
|
||||
import io.legado.app.ui.book.info.BookInfoActivity
|
||||
import io.legado.app.ui.book.manga.config.MangaFooterConfig
|
||||
import io.legado.app.ui.book.manga.config.MangaFooterSettingDialog
|
||||
import io.legado.app.ui.book.manga.rv.MangaAdapter
|
||||
import io.legado.app.ui.book.read.MangaMenu
|
||||
import io.legado.app.ui.book.read.ReadBookActivity.Companion.RESULT_DELETED
|
||||
import io.legado.app.ui.book.toc.TocActivityResult
|
||||
import io.legado.app.ui.widget.ReaderInfoBarView
|
||||
import io.legado.app.ui.widget.number.NumberPickerDialog
|
||||
import io.legado.app.ui.widget.recycler.LoadMoreView
|
||||
import io.legado.app.utils.GSON
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import io.legado.app.utils.StartActivityContract
|
||||
import io.legado.app.utils.fromJsonObject
|
||||
import io.legado.app.utils.getCompatColor
|
||||
import io.legado.app.utils.gone
|
||||
import io.legado.app.utils.observeEvent
|
||||
import io.legado.app.utils.printOnDebug
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.toastOnUi
|
||||
@@ -101,6 +108,8 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
|
||||
}
|
||||
|
||||
private var mMangaAutoPageSpeed = mInitMangaAutoPageSpeed
|
||||
private var mMangaFooterConfig: MangaFooterConfig? = null
|
||||
private val mLabelBuilder by lazy { StringBuilder() }
|
||||
|
||||
private val autoScrollHandler = Handler(Looper.getMainLooper())
|
||||
private val autoScrollRunnable = object : Runnable {
|
||||
@@ -170,6 +179,18 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
|
||||
}
|
||||
}
|
||||
loadMoreView.gone()
|
||||
mMangaFooterConfig = GSON.fromJsonObject<MangaFooterConfig>(AppConfig.mangaFooterConfig).getOrNull()
|
||||
?: MangaFooterConfig()
|
||||
observeEvent<MangaFooterConfig>(EventBus.UP_CONFIG) {
|
||||
mMangaFooterConfig = it
|
||||
AppConfig.mangaFooterConfig = GSON.toJson(it)
|
||||
upInfoBar(
|
||||
ReadManga.durChapterPagePos.plus(1),
|
||||
ReadManga.durChapterPageCount,
|
||||
ReadManga.durChapterPos.plus(1),
|
||||
ReadManga.durChapterCount
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initRecyclerView() {
|
||||
@@ -291,12 +312,37 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
|
||||
private fun upInfoBar(
|
||||
chapterPagePos: Int, chapterPageCount: Int, chapterPos: Int, chapterCount: Int,
|
||||
) {
|
||||
mMangaFooterConfig?.run {
|
||||
mLabelBuilder.clear()
|
||||
binding.infobar.isGone = this.hideFooter
|
||||
binding.infobar.textInfoAlignment =this.footerOrientation
|
||||
if (!this.hidePageNumber) {
|
||||
if (!this.hidePageNumberLabel) {
|
||||
mLabelBuilder.append(getString(R.string.manga_check_page_number))
|
||||
}
|
||||
mLabelBuilder.append("${chapterPos}/${chapterCount}").append(" ")
|
||||
}
|
||||
|
||||
if (!this.hideChapter) {
|
||||
if (!this.hideChapterLabel) {
|
||||
mLabelBuilder.append(getString(R.string.manga_check_chapter))
|
||||
}
|
||||
mLabelBuilder.append("${chapterPagePos}/${chapterPageCount}").append(" ")
|
||||
}
|
||||
|
||||
if (!this.hideProgressRatio) {
|
||||
if (!this.hideProgressRatioLabel) {
|
||||
mLabelBuilder.append(getString(R.string.manga_check_progress))
|
||||
}
|
||||
mLabelBuilder.append(
|
||||
"${
|
||||
chapterPagePos.div(chapterPageCount).times(100)
|
||||
}%"
|
||||
)
|
||||
}
|
||||
}
|
||||
binding.infobar.update(
|
||||
chapterPagePos,
|
||||
chapterPageCount,
|
||||
chapterPagePos.times(1f).div(chapterPageCount.times(1f)),
|
||||
chapterPos,
|
||||
chapterCount
|
||||
if (mLabelBuilder.isEmpty()) "" else mLabelBuilder.toString()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -471,6 +517,10 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, MangaViewModel>()
|
||||
startAutoPage()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.menu_manga_footer_config -> {
|
||||
MangaFooterSettingDialog().show(supportFragmentManager, "mangaFooterSettingDialog")
|
||||
}
|
||||
}
|
||||
return super.onCompatOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.legado.app.ui.book.manga.config
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import io.legado.app.ui.widget.ReaderInfoBarView
|
||||
|
||||
@Keep
|
||||
data class MangaFooterConfig(
|
||||
var hideChapterLabel: Boolean = false,
|
||||
var hideChapter: Boolean = false,
|
||||
var hidePageNumberLabel: Boolean = false,
|
||||
var hidePageNumber: Boolean = false,
|
||||
var hideProgressRatioLabel: Boolean = false,
|
||||
var hideProgressRatio: Boolean = false,
|
||||
var footerOrientation: Int = ReaderInfoBarView.ALIGN_LEFT,//默认靠左
|
||||
var hideFooter: Boolean = false
|
||||
)
|
||||
@@ -0,0 +1,101 @@
|
||||
package io.legado.app.ui.book.manga.config
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BaseDialogFragment
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.databinding.DialogMangaFooterSettingBinding
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.ui.widget.ReaderInfoBarView
|
||||
import io.legado.app.utils.GSON
|
||||
import io.legado.app.utils.fromJsonObject
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.setLayout
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
class MangaFooterSettingDialog : BaseDialogFragment(R.layout.dialog_manga_footer_setting) {
|
||||
val config = GSON.fromJsonObject<MangaFooterConfig>(AppConfig.mangaFooterConfig).getOrNull()
|
||||
?: MangaFooterConfig()
|
||||
private val binding by viewBinding(DialogMangaFooterSettingBinding::bind)
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
||||
binding.cbChapterLabel.run {
|
||||
isChecked = config.hideChapterLabel
|
||||
setOnCheckedChangeListener { _, isChecked ->
|
||||
config.hideChapterLabel = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
binding.cbChapter.run {
|
||||
isChecked = config.hideChapter
|
||||
setOnCheckedChangeListener { _, isChecked ->
|
||||
config.hideChapter = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
binding.cbPageNumberLabel.run {
|
||||
isChecked = config.hidePageNumberLabel
|
||||
setOnCheckedChangeListener { _, isChecked ->
|
||||
config.hidePageNumberLabel = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
binding.cbPageNumber.run {
|
||||
isChecked = config.hidePageNumber
|
||||
setOnCheckedChangeListener { _, isChecked ->
|
||||
config.hidePageNumber = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
binding.cbProgressRatioLabel.run {
|
||||
isChecked = config.hideProgressRatioLabel
|
||||
setOnCheckedChangeListener { _, isChecked ->
|
||||
config.hideProgressRatioLabel = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
binding.cbProgressRatio.run {
|
||||
isChecked = config.hideProgressRatio
|
||||
setOnCheckedChangeListener { _, isChecked ->
|
||||
config.hideProgressRatio = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
binding.rgFooterOrientation.check(if (config.footerOrientation == ReaderInfoBarView.ALIGN_CENTER) R.id.rbCenter else R.id.rbLeft)
|
||||
binding.rgFooterOrientation.setOnCheckedChangeListener { _, checkedId ->
|
||||
when (checkedId) {
|
||||
R.id.rbLeft -> {
|
||||
config.footerOrientation = ReaderInfoBarView.ALIGN_LEFT
|
||||
}
|
||||
|
||||
R.id.rbCenter -> {
|
||||
config.footerOrientation = ReaderInfoBarView.ALIGN_CENTER
|
||||
}
|
||||
}
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
|
||||
binding.rgFooter.check(if (config.hideFooter) R.id.rbDisable else R.id.rbEnable)
|
||||
binding.rgFooter.setOnCheckedChangeListener { _, checkedId ->
|
||||
when (checkedId) {
|
||||
R.id.rbEnable -> {
|
||||
config.hideFooter = false
|
||||
}
|
||||
|
||||
R.id.rbDisable -> {
|
||||
config.hideFooter = true
|
||||
}
|
||||
}
|
||||
postEvent(EventBus.UP_CONFIG, config)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import java.text.NumberFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import kotlin.math.min
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
class ReaderInfoBarView @JvmOverloads constructor(
|
||||
@@ -32,6 +33,11 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
@AttrRes defStyleAttr: Int = 0,
|
||||
) : View(context, attrs, defStyleAttr) {
|
||||
|
||||
companion object {
|
||||
const val ALIGN_LEFT = 0
|
||||
const val ALIGN_CENTER = 1
|
||||
}
|
||||
|
||||
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||
private val textBounds = Rect()
|
||||
private val timeFormat = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT)
|
||||
@@ -54,12 +60,16 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
200,
|
||||
)
|
||||
|
||||
var textInfoAlignment: Int = ALIGN_CENTER
|
||||
set(value) {
|
||||
field = value
|
||||
updateTextSize()
|
||||
invalidate()
|
||||
}
|
||||
private var timeText = timeFormat.format(Date())
|
||||
private var text: String = ""
|
||||
|
||||
private val innerHeight
|
||||
get() = height - paddingTop - paddingBottom - insetTop
|
||||
|
||||
private val innerWidth
|
||||
get() = width - paddingLeft - paddingRight - insetLeft - insetRight
|
||||
|
||||
@@ -76,12 +86,29 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
val ty = innerHeight / 2f + textBounds.height() / 2f - textBounds.bottom
|
||||
paint.textAlign = Paint.Align.LEFT
|
||||
|
||||
val textX = when (textInfoAlignment) {
|
||||
ALIGN_CENTER -> {
|
||||
val textWidth = paint.measureText(text)
|
||||
(width / 2f).coerceIn(
|
||||
paddingLeft + insetLeft + cutoutInsetLeft + textWidth / 2,
|
||||
width - paddingRight - insetRight - cutoutInsetRight - textWidth / 2
|
||||
)
|
||||
}
|
||||
|
||||
else -> (paddingLeft + insetLeft + cutoutInsetLeft).toFloat()
|
||||
}
|
||||
paint.textAlign = when (textInfoAlignment) {
|
||||
ALIGN_CENTER -> Paint.Align.CENTER
|
||||
else -> Paint.Align.LEFT
|
||||
}
|
||||
|
||||
canvas.drawTextOutline(
|
||||
text,
|
||||
(paddingLeft + insetLeft + cutoutInsetLeft).toFloat(),
|
||||
textX,
|
||||
paddingTop + insetTop + ty,
|
||||
)
|
||||
|
||||
paint.textAlign = Paint.Align.RIGHT
|
||||
canvas.drawTextOutline(
|
||||
timeText,
|
||||
@@ -117,21 +144,8 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
context.unregisterReceiver(timeReceiver)
|
||||
}
|
||||
|
||||
fun update(
|
||||
currentPage: Int,
|
||||
totalPage: Int,
|
||||
percent: Float,
|
||||
chapterIndex: Int,
|
||||
chapterCount: Int
|
||||
) {
|
||||
text = context.getString(
|
||||
R.string.book_reader_info_bar,
|
||||
chapterIndex,
|
||||
chapterCount,
|
||||
currentPage,
|
||||
totalPage,
|
||||
if (percent in 0f..1f) (percent * 100).format() else ""
|
||||
)
|
||||
fun update(label: String) {
|
||||
text = label
|
||||
updateTextSize()
|
||||
invalidate()
|
||||
}
|
||||
@@ -164,12 +178,30 @@ class ReaderInfoBarView @JvmOverloads constructor(
|
||||
|
||||
|
||||
private fun updateTextSize() {
|
||||
val str = text + timeText
|
||||
val testTextSize = 48f
|
||||
paint.textSize = testTextSize
|
||||
paint.getTextBounds(str, 0, str.length, textBounds)
|
||||
paint.textSize = testTextSize * innerHeight / textBounds.height()
|
||||
paint.getTextBounds(str, 0, str.length, textBounds)
|
||||
paint.getTextBounds(text, 0, text.length, textBounds)
|
||||
|
||||
val maxTextHeight = innerHeight * 0.8f
|
||||
val scaleFactor = min(
|
||||
maxTextHeight / textBounds.height(),
|
||||
calculateMaxWidthScale()
|
||||
)
|
||||
paint.textSize = testTextSize * scaleFactor
|
||||
|
||||
paint.getTextBounds(text, 0, text.length, textBounds)
|
||||
}
|
||||
|
||||
private fun calculateMaxWidthScale(): Float {
|
||||
return when (textInfoAlignment) {
|
||||
ALIGN_CENTER -> {
|
||||
val availableWidth = innerWidth - cutoutInsetLeft - cutoutInsetRight
|
||||
val requiredWidth = paint.measureText(text)
|
||||
if (requiredWidth > availableWidth) availableWidth / requiredWidth else 1f
|
||||
}
|
||||
|
||||
else -> 1f
|
||||
}
|
||||
}
|
||||
|
||||
private fun Canvas.drawTextOutline(text: String, x: Float, y: Float) {
|
||||
|
||||
Reference in New Issue
Block a user