新增漫画阅读模式[条漫、日漫等]

新增条漫侧边留白功能
更新滤镜功能,现在支持亮度跟随系统
其他界面更新
This commit is contained in:
HapeLee
2025-07-21 03:25:18 +08:00
parent c35177715c
commit 1701285d33
24 changed files with 585 additions and 277 deletions
@@ -190,4 +190,6 @@ object PreferKey {
const val themePref = "themePref"
const val bookshelfSortOrder = "bookshelfSortOrder"
const val showBottomView = "showBottomView"
const val mangaScrollMode = "mangaScrollMode"
const val webtoonSidePaddingDp = "webtoonSidePaddingDp"
}
@@ -403,6 +403,8 @@ data class Book(
var startDate: LocalDate? = null,
var startChapter: Int? = null, // 用户设置的起始章节
var dailyChapters: Int = 3 // 用户设置的每日更新章节数
) : Parcelable
class Converters {
@@ -5,6 +5,7 @@ import android.os.Build
import io.legato.kazusa.BuildConfig
import io.legato.kazusa.constant.PreferKey
import io.legato.kazusa.data.appDb
import io.legato.kazusa.ui.book.manga.config.MangaScrollMode
import io.legato.kazusa.utils.canvasrecorder.CanvasRecorderFactory
import io.legato.kazusa.utils.getPrefBoolean
import io.legato.kazusa.utils.getPrefInt
@@ -664,6 +665,14 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
appCtx.putPrefBoolean(PreferKey.enableMangaHorizontalScroll, value)
}
//漫画滚动方式
var mangaScrollMode: Int
get() = appCtx.getPrefInt(PreferKey.mangaScrollMode, MangaScrollMode.PAGE_RIGHT_TO_LEFT)
set(value) {
appCtx.putPrefInt(PreferKey.mangaScrollMode, value)
}
//漫画滤镜
var mangaColorFilter
get() = appCtx.getPrefString(PreferKey.mangaColorFilter, "")
set(value) {
@@ -701,5 +710,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
set(value) {
appCtx.putPrefBoolean(PreferKey.enableMangaGray, value)
}
var webtoonSidePaddingDp: Int
get() = appCtx.getPrefInt(PreferKey.webtoonSidePaddingDp, 0)
set(value) {
appCtx.putPrefInt(PreferKey.webtoonSidePaddingDp, value)
}
}
@@ -607,7 +607,7 @@ object ReadManga : CoroutineScope by MainScope() {
if (imageCount == 0 && chapter.isVolume) {
pages.add(ReaderLoading(chapter.index, -1, chapter.title, true))
} else {
pages.add(ReaderLoading(chapter.index, -1, "阅读 ${chapter.title}"))
pages.add(ReaderLoading(chapter.index, -1, "下一章 ${chapter.title}"))
pages.addAll(list)
pages.add(ReaderLoading(chapter.index, imageCount, "已读完 ${chapter.title}"))
}
@@ -12,6 +12,7 @@ import android.view.WindowManager
import android.view.animation.LinearInterpolator
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
@@ -45,6 +46,8 @@ import io.legato.kazusa.ui.book.manga.config.MangaColorFilterConfig
import io.legato.kazusa.ui.book.manga.config.MangaColorFilterDialog
import io.legato.kazusa.ui.book.manga.config.MangaFooterConfig
import io.legato.kazusa.ui.book.manga.config.MangaFooterSettingDialog
import io.legato.kazusa.ui.book.manga.config.MangaScrollMode
import io.legato.kazusa.ui.book.manga.config.MangaScrollModeDialog
import io.legato.kazusa.ui.book.manga.entities.BaseMangaPage
import io.legato.kazusa.ui.book.manga.entities.MangaPage
import io.legato.kazusa.ui.book.manga.recyclerview.MangaAdapter
@@ -77,11 +80,13 @@ import kotlin.math.ceil
class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewModel>(),
ReadManga.Callback, ChangeBookSourceDialog.CallBack, MangaMenu.CallBack,
MangaColorFilterDialog.Callback, ScrollTimer.ScrollCallback, MangaFooterSettingDialog.Callback {
MangaColorFilterDialog.Callback, ScrollTimer.ScrollCallback, MangaFooterSettingDialog.Callback,
MangaScrollModeDialog.Callback {
private val mLayoutManager by lazy {
MangaLayoutManager(this)
}
private val mAdapter: MangaAdapter by lazy {
MangaAdapter(this)
}
@@ -99,6 +104,8 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
private var mMenu: Menu? = null
private var scrollMode: Int = MangaScrollMode.PAGE_LEFT_TO_RIGHT
private var mRecyclerViewPreloader: RecyclerViewPreloader<Any>? = null
private val networkChangedListener by lazy {
@@ -192,7 +199,8 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
enableMangaEInk(AppConfig.enableMangaEInk, AppConfig.mangaEInkThreshold)
enableGray(AppConfig.enableMangaGray)
}
setHorizontalScroll(AppConfig.enableMangaHorizontalScroll)
//setHorizontalScroll(AppConfig.enableMangaHorizontalScroll)
setScrollMode(AppConfig.mangaScrollMode)
binding.recyclerView.run {
adapter = mAdapter
itemAnimator = null
@@ -201,6 +209,7 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
setDisableClickScroll(AppConfig.disableClickScroll)
setDisableMangaScale(AppConfig.disableMangaScale)
setRecyclerViewPreloader(AppConfig.mangaPreDownloadNum)
updateWebtoonSidePadding(AppConfig.webtoonSidePaddingDp)
setPreScrollListener { _, _, _, position ->
if (mAdapter.isNotEmpty()) {
val item = mAdapter.getItem(position)
@@ -431,10 +440,26 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
binding.recyclerView.smoothScrollBy(10000, 10000, mLinearInterpolator, time)
}
override fun scrollPage() {
scrollToNext()
override fun scrollPage(direction: Int) {
if (scrollMode == MangaScrollMode.WEBTOON || scrollMode == MangaScrollMode.WEBTOON_WITH_GAP) {
// 条漫平滑滚动距离
val dy =
(binding.recyclerView.height - binding.recyclerView.paddingTop - binding.recyclerView.paddingBottom) * direction
binding.recyclerView.smoothScrollBy(0, dy)
} else {
// 分页按 position 翻页
val layoutManager = binding.recyclerView.layoutManager as? LinearLayoutManager ?: return
val currentPosition = layoutManager.findFirstVisibleItemPosition()
val nextPosition = currentPosition + direction
val itemCount = binding.recyclerView.adapter?.itemCount ?: return
if (nextPosition in 0 until itemCount) {
binding.recyclerView.smoothScrollToPosition(nextPosition)
}
}
}
override val oldBook: Book?
get() = ReadManga.book
@@ -495,46 +520,11 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
}
}
R.id.menu_disable_manga_scale -> {
item.isChecked = !item.isChecked
AppConfig.disableMangaScale = item.isChecked
setDisableMangaScale(item.isChecked)
}
R.id.menu_disable_click_scroll -> {
item.isChecked = !item.isChecked
AppConfig.disableClickScroll = item.isChecked
setDisableClickScroll(item.isChecked)
}
R.id.menu_enable_horizontal_scroll -> {
item.isChecked = !item.isChecked
AppConfig.enableMangaHorizontalScroll = item.isChecked
mMenu?.findItem(R.id.menu_disable_horizontal_animation)?.isVisible = item.isChecked
setHorizontalScroll(item.isChecked)
mAdapter.notifyDataSetChanged()
}
R.id.menu_manga_color_filter -> {
binding.mangaMenu.runMenuOut()
showDialogFragment(MangaColorFilterDialog())
}
R.id.menu_enable_auto_scroll -> {
item.isChecked = !item.isChecked
mScrollTimer.isEnabled = item.isChecked
enableAutoScroll = item.isChecked
enableAutoScrollPage = false
mScrollTimer.isEnabledPage = false
if (enableAutoScroll) {
mPagerSnapHelper.attachToRecyclerView(null)
} else if (AppConfig.enableMangaHorizontalScroll) {
mPagerSnapHelper.attachToRecyclerView(binding.recyclerView)
}
}
R.id.menu_hide_manga_title -> {
item.isChecked = !item.isChecked
AppConfig.hideMangaTitle = item.isChecked
@@ -577,6 +567,40 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
showDialogFragment(MangaColorFilterDialog())
}
override fun showScrollModeDialog() {
showDialogFragment(MangaScrollModeDialog().apply {
initialScrollMode = AppConfig.mangaScrollMode
callback = this@ReadMangaActivity
})
}
//漫画模式
override fun onScrollModeChanged(mode: Int) {
AppConfig.mangaScrollMode = mode
setScrollMode(mode)
updateWebtoonSidePadding(AppConfig.webtoonSidePaddingDp)
setAutoReadEnabled(false)
}
//点击滑动
override fun onClickScrollDisabledChanged(enabled: Boolean) {
AppConfig.disableClickScroll = enabled
setDisableClickScroll(enabled)
}
//双击缩放
override fun onMangaScaleDisabledChanged(enabled: Boolean) {
AppConfig.disableMangaScale = enabled
setDisableMangaScale(enabled)
}
//侧边留白
override fun upSidePadding(paddingDp: Int) {
AppConfig.webtoonSidePaddingDp = paddingDp
updateWebtoonSidePadding(paddingDp)
}
//墨水屏
override fun updateEpaperMode(enabled: Boolean, threshold: Int) {
AppConfig.enableMangaEInk = enabled
AppConfig.enableMangaGray = false
@@ -584,12 +608,28 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
mAdapter.enableMangaEInk(enabled, threshold)
}
//灰度
override fun updateGrayMode(enabled: Boolean) {
AppConfig.enableMangaGray = enabled
AppConfig.enableMangaEInk = false
mAdapter.enableGray(enabled)
}
//自动翻页
override fun onAutoPageToggle(enabled: Boolean) {
setAutoReadEnabled(enabled)
}
//自动翻页速度
override fun onAutoPageSpeedChanged(speed: Int) {
setAutoReadEnabled(false)
AppConfig.mangaAutoPageSpeed = speed
mScrollTimer.setSpeed(speed)
setAutoReadEnabled(true)
// if (enableAutoScrollPage) {
// mScrollTimer.isEnabledPage = true
// }
}
override fun openBookInfoActivity() {
ReadManga.book?.let {
@@ -600,22 +640,27 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
}
}
override fun onAutoPageToggle(enabled: Boolean) {
mScrollTimer.isEnabledPage = enabled
mScrollTimer.isEnabled = false
enableAutoScrollPage = enabled
enableAutoScroll = false
mMenu?.findItem(R.id.menu_enable_auto_scroll)?.isChecked = false
}
override fun onAutoPageSpeedChanged(speed: Int) {
AppConfig.mangaAutoPageSpeed = speed
mScrollTimer.setSpeed(speed)
if (enableAutoScrollPage) {
mScrollTimer.isEnabledPage = true
//1 自动翻页 2 自动滚动 0 关闭
fun setAutoReadEnabled(enabled: Boolean) {
val isWebtoonMode =
scrollMode == MangaScrollMode.WEBTOON || scrollMode == MangaScrollMode.WEBTOON_WITH_GAP
if (enabled) {
if (isWebtoonMode) {
mScrollTimer.isEnabled = true
enableAutoScroll = true
enableAutoScrollPage = false
mScrollTimer.isEnabledPage = false
} else {
mScrollTimer.isEnabledPage = true
enableAutoScrollPage = true
enableAutoScroll = false
mScrollTimer.isEnabled = false
}
} else {
enableAutoScroll = false
enableAutoScrollPage = false
mScrollTimer.isEnabled = false
mScrollTimer.isEnabledPage = false
}
}
@@ -648,6 +693,70 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
return super.dispatchKeyEvent(event)
}
@SuppressLint("NotifyDataSetChanged")
private fun setScrollMode(mode: Int) {
scrollMode = mode
val isHorizontalPage =
mode == MangaScrollMode.PAGE_LEFT_TO_RIGHT || mode == MangaScrollMode.PAGE_RIGHT_TO_LEFT
val isWebtoon = mode == MangaScrollMode.WEBTOON || mode == MangaScrollMode.WEBTOON_WITH_GAP
when (mode) {
MangaScrollMode.PAGE_LEFT_TO_RIGHT -> {
mLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
mLayoutManager.reverseLayout = false
}
MangaScrollMode.PAGE_RIGHT_TO_LEFT -> {
mLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
mLayoutManager.reverseLayout = true
}
MangaScrollMode.PAGE_TOP_TO_BOTTOM,
MangaScrollMode.WEBTOON,
MangaScrollMode.WEBTOON_WITH_GAP -> {
mLayoutManager.orientation = LinearLayoutManager.VERTICAL
mLayoutManager.reverseLayout = false
}
}
mAdapter.isHorizontal = isHorizontalPage || mode == MangaScrollMode.PAGE_TOP_TO_BOTTOM
if (!isWebtoon) {
mPagerSnapHelper.attachToRecyclerView(binding.recyclerView)
} else {
mPagerSnapHelper.attachToRecyclerView(null)
}
mAdapter.notifyDataSetChanged()
}
/**
* 调整条漫侧边留白设置
* @param paddingDp 侧边留白距离,单位dp,默认16dp
*/
private fun updateWebtoonSidePadding(paddingDp: Int) {
if (scrollMode != MangaScrollMode.WEBTOON && scrollMode != MangaScrollMode.WEBTOON_WITH_GAP) {
// 非条漫模式,取消留白
binding.recyclerView.setPadding(0, 0, 0, 0)
binding.recyclerView.clipToPadding = true
return
}
binding.recyclerView.doOnLayout { recyclerView ->
val width = recyclerView.width
if (paddingDp == 0) {
recyclerView.setPadding(0, 0, 0, 0)
} else if (width > 0) {
val paddingPx = (width * paddingDp / 100).toInt()
recyclerView.setPadding(paddingPx, 0, paddingPx, 0)
}
}
}
private fun setRecyclerViewPreloader(maxPreload: Int) {
if (mRecyclerViewPreloader != null) {
binding.recyclerView.removeOnScrollListener(mRecyclerViewPreloader!!)
@@ -658,33 +767,11 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
binding.recyclerView.addOnScrollListener(mRecyclerViewPreloader!!)
}
private fun setHorizontalScroll(enable: Boolean) {
mAdapter.isHorizontal = enable
if (enable) {
if (!enableAutoScroll) {
mPagerSnapHelper.attachToRecyclerView(binding.recyclerView)
if (AppConfig.disableHorizontalAnimator) {
mPagerSnapHelper.attachToRecyclerView(null)
} else {
mPagerSnapHelper.attachToRecyclerView(binding.recyclerView)
}
}
mLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
} else {
mPagerSnapHelper.attachToRecyclerView(null)
mLayoutManager.orientation = LinearLayoutManager.VERTICAL
}
}
@SuppressLint("StringFormatMatches")
private fun upMenu(menu: Menu) {
this.mMenu = menu
menu.findItem(R.id.menu_pre_manga_number).title =
getString(R.string.pre_download_m, AppConfig.mangaPreDownloadNum)
menu.findItem(R.id.menu_disable_manga_scale).isChecked = AppConfig.disableMangaScale
menu.findItem(R.id.menu_disable_click_scroll).isChecked = AppConfig.disableClickScroll
menu.findItem(R.id.menu_enable_horizontal_scroll).isChecked =
AppConfig.enableMangaHorizontalScroll
menu.findItem(R.id.menu_hide_manga_title).isChecked = AppConfig.hideMangaTitle
menu.findItem(R.id.menu_disable_horizontal_animation).run {
@@ -129,38 +129,14 @@ class MangaFooterSettingDialog :
postEvent(EventBus.UP_MANGA_CONFIG, config)
}
binding.chipAutoPage.run {
isChecked = initialAutoPageEnabled
setOnCheckedChangeListener { _, isChecked ->
callback?.onAutoPageToggle(isChecked)
initAutoPageSpeed(isChecked)
}
}
binding.btnColorFilter.setOnClickListener {
callback?.showColorFilterConfig()
dismiss()
}
initAutoPageSpeed(initialAutoPageEnabled)
updateChapterText()
}
private fun initAutoPageSpeed(boolean: Boolean) {
TransitionManager.beginDelayedTransition(binding.rootView)
binding.scvAutoPageSpeed.run {
isEnabled = boolean
valueFormat = { "$it" }
progress = initialAutoPageSpeed
onChanged = { newValue ->
callback?.onAutoPageSpeedChanged(newValue)
}
}
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
AppConfig.mangaFooterConfig = GSON.toJson(config)
@@ -0,0 +1,27 @@
package io.legato.kazusa.ui.book.manga.config
object MangaScrollMode {
const val PAGE_LEFT_TO_RIGHT = 1 // 单页式(从左到右)
const val PAGE_RIGHT_TO_LEFT = 2 // 单页式(从右到左)
const val PAGE_TOP_TO_BOTTOM = 3 // 单页式(从上到下)
const val WEBTOON = 4 // 条漫
const val WEBTOON_WITH_GAP = 5 // 条漫(页面有空隙)
val ALL = listOf(
PAGE_LEFT_TO_RIGHT,
PAGE_RIGHT_TO_LEFT,
PAGE_TOP_TO_BOTTOM,
WEBTOON,
WEBTOON_WITH_GAP
)
fun labelOf(mode: Int): String = when (mode) {
PAGE_LEFT_TO_RIGHT -> "单页式(从左到右)"
PAGE_RIGHT_TO_LEFT -> "单页式(从右到左)"
PAGE_TOP_TO_BOTTOM -> "单页式(从上到下)"
WEBTOON -> "条漫"
WEBTOON_WITH_GAP -> "条漫(页面有空隙)"
else -> "未知"
}
}
@@ -0,0 +1,103 @@
package io.legato.kazusa.ui.book.manga.config
import android.os.Bundle
import android.view.View
import androidx.transition.TransitionManager
import com.google.android.material.chip.Chip
import io.legato.kazusa.R
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
import io.legato.kazusa.databinding.DialogMangaScrollModeBinding
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
class MangaScrollModeDialog : BaseBottomSheetDialogFragment(R.layout.dialog_manga_scroll_mode) {
private val binding by viewBinding(DialogMangaScrollModeBinding::bind)
var initialScrollMode: Int = AppConfig.mangaScrollMode
var initialAutoPageSpeed: Int = AppConfig.mangaAutoPageSpeed
var initialSidePadding: Int = AppConfig.webtoonSidePaddingDp
var initialAutoPageEnabled: Boolean = false
var callback: Callback? = null
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
initView()
}
private fun initView() {
binding.chipGroupScrollMode.removeAllViews()
MangaScrollMode.ALL.forEach { mode ->
binding.chipGroupScrollMode.addView(Chip(requireContext()).apply {
text = MangaScrollMode.labelOf(mode)
isCheckable = true
isChecked = (mode == initialScrollMode)
setOnClickListener {
AppConfig.mangaScrollMode = mode
callback?.onScrollModeChanged(mode)
binding.chipAutoPage.isChecked = false
}
})
}
binding.chipAutoPage.run {
isChecked = initialAutoPageEnabled
setOnCheckedChangeListener { _, isChecked ->
callback?.onAutoPageToggle(isChecked)
initAutoPageSpeed(isChecked)
}
}
binding.checkboxDisableClickScroll.apply {
isChecked = AppConfig.disableClickScroll
setOnCheckedChangeListener { _, isChecked ->
AppConfig.disableClickScroll = isChecked
callback?.onClickScrollDisabledChanged(isChecked)
}
}
binding.checkboxDisableMangaScale.apply {
isChecked = AppConfig.disableMangaScale
setOnCheckedChangeListener { _, isChecked ->
AppConfig.disableMangaScale = isChecked
callback?.onMangaScaleDisabledChanged(isChecked)
}
}
binding.scvPadding.apply {
valueFormat = { "$it %" }
progress = initialSidePadding
onChanged = { newValue ->
callback?.upSidePadding(newValue)
initialSidePadding = newValue
}
}
initAutoPageSpeed(initialAutoPageEnabled)
}
private fun initAutoPageSpeed(boolean: Boolean) {
TransitionManager.beginDelayedTransition(binding.rootView)
binding.scvAutoPageSpeed.run {
isEnabled = boolean
valueFormat = { "$it" }
progress = initialAutoPageSpeed
onChanged = { newValue ->
callback?.onAutoPageSpeedChanged(newValue)
initialAutoPageSpeed = newValue
}
}
}
interface Callback {
fun onAutoPageToggle(enable: Boolean)
fun onAutoPageSpeedChanged(speed: Int)
fun onScrollModeChanged(mode: Int)
fun onClickScrollDisabledChanged(disabled: Boolean)
fun onMangaScaleDisabledChanged(disabled: Boolean)
fun upSidePadding(padding: Int)
}
}
@@ -30,7 +30,6 @@ import io.legato.kazusa.ui.book.manga.entities.EpaperTransformation
import io.legato.kazusa.ui.book.manga.entities.GrayscaleTransformation
import io.legato.kazusa.ui.book.manga.entities.MangaPage
import io.legato.kazusa.ui.book.manga.entities.ReaderLoading
import io.legato.kazusa.utils.dpToPx
class MangaAdapter(private val context: Context) :
@@ -47,6 +46,8 @@ class MangaAdapter(private val context: Context) :
}
var isHorizontal = false
var enableDoublePageInLandscape = false
private val mDiffCallback: DiffUtil.ItemCallback<Any> = object : DiffUtil.ItemCallback<Any>() {
override fun areItemsTheSame(oldItem: Any, newItem: Any): Boolean {
@@ -131,19 +132,20 @@ class MangaAdapter(private val context: Context) :
inner class PageMoreViewHolder(val binding: ItemBookMangaEdgeBinding) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(item: ReaderLoading) {
val message = item.mMessage
binding.text.text = message
itemView.updateLayoutParams {
height = if (item.isVolume) {
MATCH_PARENT
} else {
96.dpToPx()
}
val message = item.mMessage ?: ""
val parts = message.split(" ", limit = 2)
if (parts.size == 2) {
binding.text.text = parts[0]
binding.textChapter.text = parts[1]
} else {
binding.text.text = message
binding.textChapter.text = ""
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when {
viewType >= TYPE_FOOTER_VIEW -> {
@@ -63,13 +63,13 @@ class ScrollTimer(
mScrollPageJob = coroutineScope.launch {
while (isActive) {
delay(distance.times(1000L))
callback.scrollPage()
callback.scrollPage(1)
}
}
}
interface ScrollCallback {
fun scrollBy(distance: Int)
fun scrollPage()
fun scrollPage(direction: Int)
}
}
@@ -243,7 +243,7 @@ class MangaMenu @JvmOverloads constructor(
}
btnAutoPage.setOnClickListener {
callBack.showFooterConfig()
callBack.showScrollModeDialog()
}
}
@@ -263,6 +263,7 @@ class MangaMenu @JvmOverloads constructor(
fun skipToPage(index: Int)
fun openCatalog()
fun showFooterConfig()
fun showScrollModeDialog()
}
}
@@ -10,6 +10,7 @@ import android.view.MotionEvent
import android.view.ViewGroup
import androidx.activity.addCallback
import androidx.activity.viewModels
import androidx.core.view.get
import androidx.core.view.postDelayed
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
@@ -17,6 +18,7 @@ import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.lifecycle.lifecycleScope
import androidx.viewpager.widget.ViewPager
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.navigation.NavigationBarView
import io.legato.kazusa.BuildConfig
import io.legato.kazusa.R
import io.legato.kazusa.base.VMBaseActivity
@@ -37,10 +39,12 @@ import io.legato.kazusa.ui.about.CrashLogsDialog
import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment
import io.legato.kazusa.ui.main.bookshelf.books.BookshelfFragment1
import io.legato.kazusa.ui.main.bookshelf.books.BookshelfFragment2
import io.legato.kazusa.ui.main.bookshelf.books.BookshelfFragment3
import io.legato.kazusa.ui.main.explore.ExploreFragment
import io.legato.kazusa.ui.main.my.MyFragment
import io.legato.kazusa.ui.main.rss.RssFragment
import io.legato.kazusa.ui.widget.dialog.TextDialog
import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.hideSoftInput
import io.legato.kazusa.utils.isCreated
import io.legato.kazusa.utils.observeEvent
@@ -48,16 +52,12 @@ import io.legato.kazusa.utils.shouldHideSoftInput
import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import io.legato.kazusa.utils.visible
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import androidx.core.view.get
import com.google.android.material.navigation.NavigationBarView
import io.legato.kazusa.ui.main.bookshelf.books.BookshelfFragment3
import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.visible
/**
* 主界面
@@ -90,7 +90,6 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
getNavigationBarView().getOrCreateBadge(R.id.menu_bookshelf)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -382,32 +381,25 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
)
}
private fun upBottomMenu() {
if (AppConfig.showBottomView)
{
getNavigationBarView().visible()
val showDiscovery = AppConfig.showDiscovery
val showRss = AppConfig.showRSS
val menu = getNavigationBarView().menu
menu.findItem(R.id.menu_discovery).isVisible = showDiscovery
menu.findItem(R.id.menu_rss).isVisible = showRss
var index = 0
if (showDiscovery) {
index++
realPositions[index] = idExplore
}
if (showRss) {
index++
realPositions[index] = idRss
}
val menu = getNavigationBarView().menu
menu.findItem(R.id.menu_discovery).isVisible = AppConfig.showDiscovery
menu.findItem(R.id.menu_rss).isVisible = AppConfig.showRSS
var index = 0
if (AppConfig.showDiscovery) {
index++
realPositions[index] = idMy
bottomMenuCount = index + 1
adapter.notifyDataSetChanged()
realPositions[index] = idExplore
}
else getNavigationBarView().gone()
if (AppConfig.showRSS) {
index++
realPositions[index] = idRss
}
index++
realPositions[index] = idMy
bottomMenuCount = index + 1
adapter.notifyDataSetChanged()
if (AppConfig.showBottomView) getNavigationBarView().visible()
else binding.bottomNavigationView?.gone()
}
private fun upHomePage() {
@@ -450,7 +442,6 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
}
private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
@@ -44,6 +44,12 @@ class DetailSeekBar @JvmOverloads constructor(
binding.slider.valueTo = value.toFloat()
}
var min: Int
get() = binding.slider.valueFrom.toInt()
set(value) {
binding.slider.valueFrom = value.toFloat()
}
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailSeekBar)
isBottomBackground =
@@ -57,17 +63,6 @@ class DetailSeekBar @JvmOverloads constructor(
binding.slider.valueTo = typedArray.getInteger(R.styleable.DetailSeekBar_max, 0).toFloat()
typedArray.recycle()
binding.ivSeekPlus.setOnClickListener {
val newValue = (binding.slider.value + 1).coerceAtMost(binding.slider.valueTo)
binding.slider.value = newValue
onChanged?.invoke(newValue.toInt())
}
binding.ivSeekReduce.setOnClickListener {
val newValue = (binding.slider.value - 1).coerceAtLeast(binding.slider.valueFrom)
binding.slider.value = newValue
onChanged?.invoke(newValue.toInt())
}
binding.slider.addOnChangeListener { _, value, fromUser ->
upValue(value.toInt())
@@ -23,6 +23,7 @@ class SimpleCounterView @JvmOverloads constructor(
private var _progress = 0
private var _max = 100
private var _min = 0
private val isBottomBackground: Boolean
var valueFormat: ((Int) -> String)? = null
@@ -39,7 +40,7 @@ class SimpleCounterView @JvmOverloads constructor(
var progress: Int
get() = _progress
set(value) {
_progress = value.coerceIn(0, _max)
_progress = value.coerceIn(_min, _max)
updateValue()
}
@@ -51,11 +52,22 @@ class SimpleCounterView @JvmOverloads constructor(
updateValue()
}
var min: Int
get() = _min
set(value) {
_min = value
_progress = _progress.coerceAtLeast(_min)
updateValue()
}
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailSeekBar)
isBottomBackground = typedArray.getBoolean(R.styleable.DetailSeekBar_isBottomBackground, false)
val title = typedArray.getText(R.styleable.DetailSeekBar_title)
_max = typedArray.getInt(R.styleable.DetailSeekBar_max, 100)
_min = typedArray.getInt(R.styleable.DetailSeekBar_min, 0)
_progress = _progress.coerceIn(_min, _max)
typedArray.recycle()
binding.tvSeekTitle.text = title
@@ -70,7 +82,7 @@ class SimpleCounterView @JvmOverloads constructor(
}
binding.ivSeekReduce.setOnClickListener {
if (_progress > 0) {
if (_progress > _min) {
_progress--
updateValue()
onChanged?.invoke(_progress)
@@ -119,6 +131,7 @@ class SimpleCounterView @JvmOverloads constructor(
customView {
val detailSeekBar = DetailSeekBar(ctx).apply {
max = _max
min = _min
progress = _progress
valueFormat = this@SimpleCounterView.valueFormat
setTitle(binding.tvSeekTitle.text)
@@ -168,7 +181,7 @@ class SimpleCounterView @JvmOverloads constructor(
private val decrementRunnable = object : Runnable {
override fun run() {
if (_progress > 0) {
if (_progress > _min) {
_progress--
updateValue()
onChanged?.invoke(_progress)
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M200,700Q226,700 243,683Q260,666 260,640Q260,614 243,597Q226,580 200,580Q174,580 157,597Q140,614 140,640Q140,666 157,683Q174,700 200,700ZM360,520Q377,520 388.5,508.5Q400,497 400,480Q400,463 388.5,451.5Q377,440 360,440Q343,440 331.5,451.5Q320,463 320,480Q320,497 331.5,508.5Q343,520 360,520ZM360,360Q377,360 388.5,348.5Q400,337 400,320Q400,303 388.5,291.5Q377,280 360,280Q343,280 331.5,291.5Q320,303 320,320Q320,337 331.5,348.5Q343,360 360,360ZM120,840L120,760L840,760L840,840L120,840ZM200,380Q226,380 243,363Q260,346 260,320Q260,294 243,277Q226,260 200,260Q174,260 157,277Q140,294 140,320Q140,346 157,363Q174,380 200,380ZM200,540Q226,540 243,523Q260,506 260,480Q260,454 243,437Q226,420 200,420Q174,420 157,437Q140,454 140,480Q140,506 157,523Q174,540 200,540ZM360,680Q377,680 388.5,668.5Q400,657 400,640Q400,623 388.5,611.5Q377,600 360,600Q343,600 331.5,611.5Q320,623 320,640Q320,657 331.5,668.5Q343,680 360,680ZM680,660Q689,660 694.5,654.5Q700,649 700,640Q700,631 694.5,625.5Q689,620 680,620Q671,620 665.5,625.5Q660,631 660,640Q660,649 665.5,654.5Q671,660 680,660ZM120,200L120,120L840,120L840,200L120,200ZM680,340Q689,340 694.5,334.5Q700,329 700,320Q700,311 694.5,305.5Q689,300 680,300Q671,300 665.5,305.5Q660,311 660,320Q660,329 665.5,334.5Q671,340 680,340ZM680,500Q689,500 694.5,494.5Q700,489 700,480Q700,471 694.5,465.5Q689,460 680,460Q671,460 665.5,465.5Q660,471 660,480Q660,489 665.5,494.5Q671,500 680,500ZM520,360Q537,360 548.5,348.5Q560,337 560,320Q560,303 548.5,291.5Q537,280 520,280Q503,280 491.5,291.5Q480,303 480,320Q480,337 491.5,348.5Q503,360 520,360ZM520,520Q537,520 548.5,508.5Q560,497 560,480Q560,463 548.5,451.5Q537,440 520,440Q503,440 491.5,451.5Q480,463 480,480Q480,497 491.5,508.5Q503,520 520,520ZM520,680Q537,680 548.5,668.5Q560,657 560,640Q560,623 548.5,611.5Q537,600 520,600Q503,600 491.5,611.5Q480,623 480,640Q480,657 491.5,668.5Q503,680 520,680ZM120,760L120,760L120,200L120,200L120,760Z" />
</vector>
+8 -7
View File
@@ -8,7 +8,8 @@
<io.legato.kazusa.ui.book.manga.recyclerview.WebtoonFrame
android:id="@+id/webtoon_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/black">
<io.legato.kazusa.ui.book.manga.recyclerview.WebtoonRecyclerView
android:id="@+id/recycler_view"
@@ -48,20 +49,19 @@
android:gravity="center"
android:orientation="vertical">
<ProgressBar
<com.google.android.material.progressindicator.CircularProgressIndicator
style="@style/Widget.Material3.CircularProgressIndicator.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:indicatorSize="36dp"
app:trackCornerRadius="99dp"
app:trackThickness="3dp" />
app:indicatorSize="40dp" />
<TextView
android:id="@+id/tv_loading_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginTop="8dp"
android:textColor="?attr/colorSurface"
android:text="@string/loading" />
</LinearLayout>
@@ -78,10 +78,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<io.legato.kazusa.ui.widget.text.AccentTextView
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_retry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_margin="16dp"
android:text="重新加载"
android:textSize="18sp"
@@ -48,8 +48,8 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/footer"
android:textStyle="bold"
android:textSize="14sp" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
@@ -165,35 +165,10 @@
android:text="2.1%" />
</com.google.android.material.chip.ChipGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.chip.Chip
android:id="@+id/chip_autoPage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/enable_auto_page_scroll" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<io.legato.kazusa.ui.widget.SimpleCounterView
android:id="@+id/scv_autoPageSpeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:max="100"
app:title="翻页速度" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_color_filter"
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
style="@style/Widget.Material3.Button.TonalButton"
app:icon="@drawable/ic_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/manga_color_filter" />
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rootView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<View
android:layout_width="36dp"
android:layout_height="4dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"
android:background="@drawable/bg_bottom_sheet_handle" />
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="漫画设置"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:text="阅读模式"
android:textStyle="bold" />
<com.google.android.material.chip.ChipGroup
android:id="@+id/chipGroupScrollMode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:singleLine="false"
app:chipSpacingVertical="0dp"
app:selectionRequired="true"
app:singleSelection="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:text="自动阅读"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.chip.Chip
android:id="@+id/chip_autoPage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/enable_auto_page_scroll" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<io.legato.kazusa.ui.widget.SimpleCounterView
android:id="@+id/scv_autoPageSpeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:max="100"
app:min="1"
app:title="翻页速度" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_webtoon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:text="条漫"
android:textStyle="bold" />
<io.legato.kazusa.ui.widget.DetailSeekBar
android:id="@+id/scv_Padding"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:max="30"
app:title="侧边留白" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="12dp">
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkboxDisableClickScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/disable_manga_click_scroll" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkboxDisableMangaScale"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/disable_manga_scale" />
</LinearLayout>
</LinearLayout>
@@ -1,16 +1,38 @@
<?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:layout_width="match_parent"
android:layout_height="96dp"
android:layout_height="wrap_content"
android:background="@color/book_ant_10">
<TextView
android:id="@+id/text"
<LinearLayout
android:id="@+id/ll_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="@android:color/white"
android:textStyle="bold"
tools:text="上一章节:第一话" />
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:padding="32dp">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:autoSizeTextType="uniform"
android:text="已读完"
android:textColor="?attr/colorSurface"
android:textStyle="bold" />
<TextView
android:id="@+id/textChapter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:autoSizeTextType="uniform"
android:text="下一章123"
android:textColor="?attr/colorSurface"
android:textSize="22sp"
android:textStyle="bold" />
</LinearLayout>
</FrameLayout>
@@ -21,33 +21,32 @@
android:layout_height="match_parent"
android:background="@color/book_ant_10">
<ProgressBar
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/loading"
style="@style/Widget.Material3.CircularProgressIndicator.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.Material3.CircularProgressIndicator"
android:layout_gravity="center"
android:indeterminate="true"
android:indeterminateTint="@color/white"
android:progressTint="@color/white"
app:indicatorColor="@color/white"
app:indicatorSize="36dp"
app:trackCornerRadius="99dp"
app:trackThickness="3dp" />
app:indicatorSize="64dp" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/retry"
style="@style/Widget.Material3.Button.TonalButton"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="8dp"
android:text="重新加载"
android:textColor="@color/white"
android:textSize="18sp"
android:textColor="?attr/colorSurfaceVariant"
app:backgroundTint="?attr/colorOnSurface"
app:cornerRadius="12dp"
app:icon="@drawable/ic_refresh"
app:iconSize="24sp"
app:iconTint="?attr/colorSurfaceVariant"
android:visibility="gone"
app:backgroundTint="@color/white"
app:cornerRadius="10dp"
tools:visibility="visible" />
<TextView
@@ -56,9 +55,10 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="0%"
android:textColor="@color/white"
android:textColor="?attr/colorSurfaceVariant"
android:visibility="gone"
tools:visibility="visible" />
</FrameLayout>
</FrameLayout>
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_marginVertical="4dp"
android:layout_marginVertical="8dp"
android:orientation="vertical">
<LinearLayout
@@ -12,6 +11,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingHorizontal="16dp"
android:paddingTop="8dp"
android:paddingBottom="4dp">
@@ -19,10 +19,9 @@
android:id="@+id/tv_seek_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:singleLine="true"
android:text="seek"
tools:ignore="HardcodedText" />
android:textStyle="bold" />
<View
android:layout_width="0dp"
@@ -32,7 +31,6 @@
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
app:strokeWidth="0dp"
app:cardBackgroundColor="?attr/colorSurfaceVariant">
<TextView
@@ -47,35 +45,10 @@
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
<com.google.android.material.slider.Slider
android:id="@+id/slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<com.google.android.material.button.MaterialButton
android:id="@+id/iv_seek_reduce"
android:layout_width="48dp"
android:layout_height="48dp"
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:contentDescription="@string/reduce"
app:icon="@drawable/ic_reduce" />
<io.legato.kazusa.lib.theme.view.ThemeSlider
android:id="@+id/slider"
android:layout_width="0dp"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
app:labelBehavior="gone"
android:layout_weight="4"
android:stepSize="1"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/iv_seek_plus"
android:layout_width="48dp"
android:layout_height="48dp"
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:contentDescription="@string/plus"
app:icon="@drawable/ic_add" />
</LinearLayout>
android:stepSize="1" />
</LinearLayout>
-27
View File
@@ -24,33 +24,6 @@
android:title="@string/pre_download"
app:showAsAction="never" />
<item
android:id="@+id/menu_disable_manga_scale"
android:checkable="true"
android:checked="false"
android:title="@string/disable_manga_scale"
app:showAsAction="never" />
<item
android:id="@+id/menu_disable_click_scroll"
android:checkable="true"
android:checked="false"
android:title="@string/disable_manga_click_scroll"
app:showAsAction="never" />
<item
android:id="@+id/menu_enable_auto_scroll"
android:checkable="true"
android:checked="false"
android:title="@string/enable_auto_scroll"
app:showAsAction="never" />
<item
android:id="@+id/menu_enable_horizontal_scroll"
android:checkable="true"
android:checked="false"
android:title="@string/enable_manga_horizontal_scroll"
app:showAsAction="never" />
<item
android:id="@+id/menu_disable_horizontal_animation"
+1 -1
View File
@@ -1194,7 +1194,7 @@
<string name="disable_manga_click_scroll">禁用点击翻页</string>
<string name="enable_auto_page_scroll">开启自动翻页</string>
<string name="manga_auto_page_speed">翻页速度 %s</string>
<string name="enable_auto_scroll">开启滚动</string>
<string name="enable_auto_scroll">开启自动滚动</string>
<string name="manga_footer_config">页脚配置</string>
<string name="setting_manga_auto_page_speed">设置自动翻页速度</string>
<string name="book_reader_info_bar">页数. %1$d/%2$d 章节. %3$d/%4$d -> %5$s%%</string>
+1
View File
@@ -80,6 +80,7 @@
<declare-styleable name="DetailSeekBar">
<attr name="title" />
<attr name="max" />
<attr name="min" />
<attr name="isBottomBackground" />
</declare-styleable>