diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 8b1acd8d9..1cb677260 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,6 +2,10 @@ * 旧版数据导入教程: * 先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 +**2020/02/24** +* 滚动暂时可以滚了,先这样吧,头大 +* 紧急修复朗读报错的bug + **2020/02/23** * 修复BUG * 本地目录正则自定义完成 diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index ce49d6023..50ab1c873 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -37,4 +37,5 @@ object PreferKey { const val lastBackup = "lastBackup" const val bodyIndent = "textIndent" const val shareLayout = "shareLayout" + const val readStyleSelect = "readStyleSelect" } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt index a4227619b..c7560b819 100644 --- a/app/src/main/java/io/legado/app/help/BookHelp.kt +++ b/app/src/main/java/io/legado/app/help/BookHelp.kt @@ -237,8 +237,14 @@ object BookHelp { private var bookName: String? = null private var bookOrigin: String? = null private var replaceRules: List = arrayListOf() - val bodyIndent - get() = " ".repeat(App.INSTANCE.getPrefInt(PreferKey.bodyIndent, 2)) + var bodyIndentCount = App.INSTANCE.getPrefInt(PreferKey.bodyIndent, 2) + set(value) { + field = value + App.INSTANCE.putPrefInt(PreferKey.bodyIndent, value) + bodyIndent = " ".repeat(value) + } + var bodyIndent = " ".repeat(bodyIndentCount) + fun disposeContent( title: String, @@ -268,7 +274,9 @@ object BookHelp { } } } - c = "$title\n$c" + if (!c.substringBefore("\n").contains(title)) { + c = "$title\n$c" + } when (AppConfig.chineseConverterType) { 1 -> c = ZhConvertBootstrap.newInstance().toSimple(c) 2 -> c = ZhConvertBootstrap.newInstance().toTraditional(c) diff --git a/app/src/main/java/io/legado/app/help/FirstTopListUpCallback.kt b/app/src/main/java/io/legado/app/help/FirstTopListUpCallback.kt deleted file mode 100644 index a35f0cd8c..000000000 --- a/app/src/main/java/io/legado/app/help/FirstTopListUpCallback.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.legado.app.help - -import androidx.recyclerview.widget.ListUpdateCallback -import androidx.recyclerview.widget.RecyclerView -import io.legado.app.base.adapter.ItemViewHolder - -class FirstTopListUpCallback : ListUpdateCallback { - var firstInsert = -1 - lateinit var adapter: RecyclerView.Adapter - - override fun onChanged(position: Int, count: Int, payload: Any?) { - adapter.notifyItemRangeChanged(position, count, payload) - } - - override fun onMoved(fromPosition: Int, toPosition: Int) { - if (toPosition == 0) { - firstInsert = 0 - } - adapter.notifyItemMoved(fromPosition, toPosition) - } - - override fun onInserted(position: Int, count: Int) { - if (firstInsert == -1 || firstInsert > position) { - firstInsert = position - } - adapter.notifyItemRangeInserted(position, count) - } - - override fun onRemoved(position: Int, count: Int) { - adapter.notifyItemRangeRemoved(position, count) - } - - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt index 75777d51b..3b05df869 100644 --- a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt +++ b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt @@ -6,6 +6,7 @@ import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import io.legado.app.App import io.legado.app.R +import io.legado.app.constant.PreferKey import io.legado.app.help.coroutine.Coroutine import io.legado.app.ui.book.read.page.ChapterProvider import io.legado.app.utils.* @@ -23,12 +24,25 @@ object ReadBookConfig { val json = String(App.INSTANCE.assets.open(readConfigFileName).readBytes()) GSON.fromJsonArray(json)!! } - val durConfig - get() = getConfig(styleSelect) - - var styleSelect - get() = App.INSTANCE.getPrefInt("readStyleSelect") - set(value) = App.INSTANCE.putPrefInt("readStyleSelect", value) + val durConfig get() = getConfig(styleSelect) + private val shareConfig get() = getConfig(5) + var styleSelect = App.INSTANCE.getPrefInt(PreferKey.readStyleSelect) + set(value) { + field = value + App.INSTANCE.putPrefInt(PreferKey.readStyleSelect, value) + } + var shareLayout = App.INSTANCE.getPrefBoolean(PreferKey.shareLayout) + set(value) { + field = value + App.INSTANCE.putPrefBoolean(PreferKey.shareLayout) + } + var pageAnim = App.INSTANCE.getPrefInt(PreferKey.pageAnim) + set(value) { + field = value + isScroll = value == 3 + App.INSTANCE.putPrefInt(PreferKey.pageAnim, value) + } + var isScroll = pageAnim == 3 var bg: Drawable? = null init { @@ -40,6 +54,9 @@ object ReadBookConfig { if (configList.size < 5) { resetAll() } + if (configList.size < 6) { + configList.add(Config()) + } return configList[index] } @@ -94,17 +111,118 @@ object ReadBookConfig { } } - data class Config( - var bgStr: String = "#EEEEEE",//白天背景 - var bgStrNight: String = "#000000",//夜间背景 - var bgType: Int = 0,//白天背景类型 - var bgTypeNight: Int = 0,//夜间背景类型 - var darkStatusIcon: Boolean = true,//白天是否暗色状态栏 - var darkStatusIconNight: Boolean = false,//晚上是否暗色状态栏 - var textColor: String = "#3E3D3B",//白天文字颜色 - var textColorNight: String = "#adadad",//夜间文字颜色 + //配置写入读取 + var hideStatusBar = App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar) + var hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar) + var textBold: Boolean + get() = if (shareLayout) shareConfig.textBold else durConfig.textBold + set(value) = if (shareLayout) shareConfig.textBold = value else durConfig.textBold = value + + var textSize: Int + get() = if (shareLayout) shareConfig.textSize else durConfig.textSize + set(value) = if (shareLayout) shareConfig.textSize = value else durConfig.textSize = value + + var letterSpacing: Float + get() = if (shareLayout) shareConfig.letterSpacing else durConfig.letterSpacing + set(value) = + if (shareLayout) shareConfig.letterSpacing = value else durConfig.letterSpacing = value + + var lineSpacingExtra: Int + get() = if (shareLayout) shareConfig.lineSpacingExtra else durConfig.lineSpacingExtra + set(value) = + if (shareLayout) shareConfig.lineSpacingExtra = value + else durConfig.lineSpacingExtra = value + + var paragraphSpacing: Int + get() = if (shareLayout) shareConfig.paragraphSpacing else durConfig.paragraphSpacing + set(value) = + if (shareLayout) shareConfig.paragraphSpacing = value + else durConfig.paragraphSpacing = value + + var titleCenter: Boolean + get() = if (shareLayout) shareConfig.titleCenter else durConfig.titleCenter + set(value) = + if (shareLayout) shareConfig.titleCenter = value else durConfig.titleCenter = value + + var paddingBottom: Int + get() = if (shareLayout) shareConfig.paddingBottom else durConfig.paddingBottom + set(value) = + if (shareLayout) shareConfig.paddingBottom = value else durConfig.paddingBottom = value + + var paddingLeft: Int + get() = if (shareLayout) shareConfig.paddingLeft else durConfig.paddingLeft + set(value) = + if (shareLayout) shareConfig.paddingLeft = value else durConfig.paddingLeft = value + + var paddingRight: Int + get() = if (shareLayout) shareConfig.paddingRight else durConfig.paddingRight + set(value) = + if (shareLayout) shareConfig.paddingRight = value else durConfig.paddingRight = value + + var paddingTop: Int + get() = if (shareLayout) shareConfig.paddingTop else durConfig.paddingTop + set(value) = + if (shareLayout) shareConfig.paddingTop = value else durConfig.paddingTop = value + + var headerPaddingBottom: Int + get() = if (shareLayout) shareConfig.headerPaddingBottom else durConfig.headerPaddingBottom + set(value) = + if (shareLayout) shareConfig.headerPaddingBottom = value + else durConfig.headerPaddingBottom = value + + var headerPaddingLeft: Int + get() = if (shareLayout) shareConfig.headerPaddingLeft else durConfig.headerPaddingLeft + set(value) = + if (shareLayout) shareConfig.headerPaddingLeft = value + else durConfig.headerPaddingLeft = value + + var headerPaddingRight: Int + get() = if (shareLayout) shareConfig.headerPaddingRight else durConfig.headerPaddingRight + set(value) = + if (shareLayout) shareConfig.headerPaddingRight = value + else durConfig.headerPaddingRight = value + + var headerPaddingTop: Int + get() = if (shareLayout) shareConfig.headerPaddingTop else durConfig.headerPaddingTop + set(value) = + if (shareLayout) shareConfig.headerPaddingTop = value + else durConfig.headerPaddingTop = value + + var footerPaddingBottom: Int + get() = if (shareLayout) shareConfig.footerPaddingBottom else durConfig.footerPaddingBottom + set(value) = + if (shareLayout) shareConfig.footerPaddingBottom = value + else durConfig.footerPaddingBottom = value + + var footerPaddingLeft: Int + get() = if (shareLayout) shareConfig.footerPaddingLeft else durConfig.footerPaddingLeft + set(value) = + if (shareLayout) shareConfig.footerPaddingLeft = value + else durConfig.footerPaddingLeft = value + + var footerPaddingRight: Int + get() = if (shareLayout) shareConfig.footerPaddingRight else durConfig.footerPaddingRight + set(value) = + if (shareLayout) shareConfig.footerPaddingRight = value + else durConfig.footerPaddingRight = value + + var footerPaddingTop: Int + get() = if (shareLayout) shareConfig.footerPaddingTop else durConfig.footerPaddingTop + set(value) = + if (shareLayout) shareConfig.footerPaddingTop = value + else durConfig.footerPaddingTop = value + + class Config( + private var bgStr: String = "#EEEEEE",//白天背景 + private var bgStrNight: String = "#000000",//夜间背景 + private var bgType: Int = 0,//白天背景类型 + private var bgTypeNight: Int = 0,//夜间背景类型 + private var darkStatusIcon: Boolean = true,//白天是否暗色状态栏 + private var darkStatusIconNight: Boolean = false,//晚上是否暗色状态栏 + private var textColor: String = "#3E3D3B",//白天文字颜色 + private var textColorNight: String = "#ADADAD",//夜间文字颜色 var textBold: Boolean = false,//是否粗体字 - var textSize: Int = 15,//文字大小 + var textSize: Int = 20,//文字大小 var letterSpacing: Float = 1f,//字间距 var lineSpacingExtra: Int = 12,//行间距 var paragraphSpacing: Int = 12,//段距 @@ -138,7 +256,7 @@ object ReadBookConfig { } else { textColor = "#${color.hexString}" } - ChapterProvider.upStyle(this) + ChapterProvider.upStyle() } fun setStatusIconDark(isDark: Boolean) { diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt index c7de266ca..4076c96a7 100644 --- a/app/src/main/java/io/legado/app/help/storage/Backup.kt +++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt @@ -100,12 +100,16 @@ object Backup { for (fileName in backupFileNames) { val file = File(backupPath + File.separator + fileName) if (file.exists()) { - val doc = treeDoc.findFile(fileName) ?: treeDoc.createFile("", fileName) + var doc = treeDoc.findFile(fileName) + if (null != doc && doc.exists()) { + doc.delete() + } + doc = treeDoc.createFile("", fileName) doc?.let { DocumentUtils.writeText( context, file.readText(), - doc.uri + it.uri ) } } diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt index 123332df6..9fd939f74 100644 --- a/app/src/main/java/io/legado/app/help/storage/Restore.kt +++ b/app/src/main/java/io/legado/app/help/storage/Restore.kt @@ -104,7 +104,14 @@ object Restore { else -> Unit } edit.putInt(PreferKey.versionCode, App.INSTANCE.versionCode) - edit.commit() + edit.apply() + } + ReadBookConfig.apply { + styleSelect = App.INSTANCE.getPrefInt(PreferKey.readStyleSelect) + shareLayout = App.INSTANCE.getPrefBoolean(PreferKey.shareLayout) + pageAnim = App.INSTANCE.getPrefInt(PreferKey.pageAnim) + hideStatusBar = App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar) + hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar) } } LauncherIconHelp.changeIcon(App.INSTANCE.getPrefString(PreferKey.launcherIcon)) diff --git a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt index 12083c652..00c9d0522 100644 --- a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt +++ b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt @@ -45,7 +45,7 @@ class MediaButtonReceiver : BroadcastReceiver() { } } } - return false + return true } private fun readAloud(context: Context) { diff --git a/app/src/main/java/io/legado/app/receiver/TimeElectricityReceiver.kt b/app/src/main/java/io/legado/app/receiver/TimeBatteryReceiver.kt similarity index 85% rename from app/src/main/java/io/legado/app/receiver/TimeElectricityReceiver.kt rename to app/src/main/java/io/legado/app/receiver/TimeBatteryReceiver.kt index 765d05b3e..ce2e04fbe 100644 --- a/app/src/main/java/io/legado/app/receiver/TimeElectricityReceiver.kt +++ b/app/src/main/java/io/legado/app/receiver/TimeBatteryReceiver.kt @@ -9,12 +9,12 @@ import io.legado.app.constant.EventBus import io.legado.app.utils.postEvent -class TimeElectricityReceiver : BroadcastReceiver() { +class TimeBatteryReceiver : BroadcastReceiver() { companion object { - fun register(context: Context): TimeElectricityReceiver { - val receiver = TimeElectricityReceiver() + fun register(context: Context): TimeBatteryReceiver { + val receiver = TimeBatteryReceiver() val filter = IntentFilter() filter.addAction(Intent.ACTION_TIME_TICK) filter.addAction(Intent.ACTION_BATTERY_CHANGED) diff --git a/app/src/main/java/io/legado/app/service/help/ReadBook.kt b/app/src/main/java/io/legado/app/service/help/ReadBook.kt index d038ad600..207c34ec6 100644 --- a/app/src/main/java/io/legado/app/service/help/ReadBook.kt +++ b/app/src/main/java/io/legado/app/service/help/ReadBook.kt @@ -26,10 +26,10 @@ object ReadBook { var book: Book? = null var inBookshelf = false var chapterSize = 0 - var callBack: CallBack? = null var durChapterIndex = 0 var durPageIndex = 0 var isLocalBook = true + var callBack: CallBack? = null var prevTextChapter: TextChapter? = null var curTextChapter: TextChapter? = null var nextTextChapter: TextChapter? = null @@ -127,7 +127,13 @@ object ReadBook { saveRead() } - fun curPageChanged() { + fun setPageIndex(pageIndex: Int) { + durPageIndex = pageIndex + saveRead() + curPageChanged() + } + + private fun curPageChanged() { callBack?.upPageProgress() if (BaseReadAloudService.isRun) { readAloud(!BaseReadAloudService.pause) @@ -306,7 +312,7 @@ object ReadBook { } interface CallBack { - fun upContent(position: Int = 0) + fun upContent(relativePosition: Int = 0) fun upView() fun upPageProgress() fun contentLoadFinish() diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt index e3ca00964..671736dc8 100644 --- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt @@ -19,8 +19,8 @@ import io.legado.app.lib.theme.ATH import io.legado.app.ui.book.group.GroupManageDialog import io.legado.app.ui.book.group.GroupSelectDialog import io.legado.app.ui.widget.SelectActionBar +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint -import io.legado.app.utils.getVerticalDivider import io.legado.app.utils.getViewModel import kotlinx.android.synthetic.main.activity_arrange_book.* @@ -60,7 +60,7 @@ class ArrangeBookActivity : VMBaseActivity(R.layout.activi private fun initView() { ATH.applyEdgeEffectColor(recycler_view) recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) adapter = ArrangeBookAdapter(this, this) recycler_view.adapter = adapter select_action_bar.setMainActionText(R.string.move_to_group) diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt index e982cbbe0..1a4322da6 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt @@ -28,8 +28,8 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.customView import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.yesButton +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint -import io.legado.app.utils.getVerticalDivider import io.legado.app.utils.getViewModel import io.legado.app.utils.requestInputMethod import kotlinx.android.synthetic.main.dialog_edit_text.view.* @@ -77,7 +77,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { .isChecked = AppConst.bookGroupAudioShow adapter = GroupAdapter(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter App.db.bookGroupDao().liveDataAll().observe(viewLifecycleOwner, Observer { val diffResult = diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt index 2d90a82e2..b290bc5df 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt @@ -28,8 +28,8 @@ import io.legado.app.lib.dialogs.customView import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.yesButton import io.legado.app.lib.theme.accentColor +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint -import io.legado.app.utils.getVerticalDivider import io.legado.app.utils.getViewModel import io.legado.app.utils.requestInputMethod import kotlinx.android.synthetic.main.dialog_book_group_picker.* @@ -98,7 +98,7 @@ class GroupSelectDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { tool_bar.menu.findItem(R.id.menu_group_audio).isVisible = false adapter = GroupAdapter(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter val itemTouchCallback = ItemTouchCallback() itemTouchCallback.onItemTouchCallbackListener = adapter diff --git a/app/src/main/java/io/legado/app/ui/book/read/Help.kt b/app/src/main/java/io/legado/app/ui/book/read/Help.kt index 3a3e04191..549b7b987 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/Help.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/Help.kt @@ -10,7 +10,6 @@ import android.view.View.NO_ID import android.widget.EditText import io.legado.app.App import io.legado.app.R -import io.legado.app.constant.PreferKey import io.legado.app.data.entities.Bookmark import io.legado.app.help.AppConfig import io.legado.app.help.ReadBookConfig @@ -23,7 +22,6 @@ import io.legado.app.lib.theme.ThemeStore import io.legado.app.service.help.Download import io.legado.app.service.help.ReadBook import io.legado.app.utils.applyTint -import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.requestInputMethod import kotlinx.android.synthetic.main.dialog_download_choice.view.* import kotlinx.android.synthetic.main.dialog_edit_text.view.* @@ -42,15 +40,14 @@ object Help { or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_IMMERSIVE or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) - val hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar) - if (hideNavigationBar) { + if (ReadBookConfig.hideNavigationBar) { flag = flag or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION } if (toolBarHide) { - if (App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar)) { + if (ReadBookConfig.hideStatusBar) { flag = flag or View.SYSTEM_UI_FLAG_FULLSCREEN } - if (hideNavigationBar) { + if (ReadBookConfig.hideNavigationBar) { flag = flag or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index 7d3d747aa..16b198626 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -7,6 +7,7 @@ import android.net.Uri import android.os.Bundle import android.os.Handler import android.view.* +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import androidx.appcompat.view.menu.MenuItemImpl import androidx.core.view.get import androidx.core.view.isVisible @@ -25,7 +26,7 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.okButton import io.legado.app.lib.theme.accentColor -import io.legado.app.receiver.TimeElectricityReceiver +import io.legado.app.receiver.TimeBatteryReceiver import io.legado.app.service.BaseReadAloudService import io.legado.app.service.help.ReadAloud import io.legado.app.service.help.ReadBook @@ -80,7 +81,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo private val keepScreenRunnable: Runnable = Runnable { Help.keepScreenOn(window, false) } private var screenTimeOut: Long = 0 - private var timeElectricityReceiver: TimeElectricityReceiver? = null + private var timeBatteryReceiver: TimeBatteryReceiver? = null override val pageFactory: TextPageFactory get() = page_view.pageFactory override val headerHeight: Int get() = page_view.curPage.headerHeight @@ -105,15 +106,15 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo override fun onResume() { super.onResume() upSystemUiVisibility() - timeElectricityReceiver = TimeElectricityReceiver.register(this) + timeBatteryReceiver = TimeBatteryReceiver.register(this) page_view.upTime() } override fun onPause() { super.onPause() - timeElectricityReceiver?.let { + timeBatteryReceiver?.let { unregisterReceiver(it) - timeElectricityReceiver = null + timeBatteryReceiver = null } upSystemUiVisibility() } @@ -379,20 +380,17 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo textActionMenu ?: let { textActionMenu = TextActionMenu(this, this) } + val x = cursor_left.x.toInt() + cursor_left.width + val y = if (cursor_left.y - statusBarHeight > ReadBookConfig.textSize.dp * 1.5 + 20.dp) { + (page_view.height - cursor_left.y + ReadBookConfig.textSize.dp * 1.5).toInt() + } else { + (page_view.height - cursor_left.y - cursor_left.height - 40.dp).toInt() + } textActionMenu?.let { popup -> if (!popup.isShowing) { - popup.showAtLocation( - cursor_left, - Gravity.BOTTOM or Gravity.START, - cursor_left.x.toInt() + cursor_left.width, - page_view.height - cursor_left.y.toInt() + ReadBookConfig.durConfig.textSize.dp + popup.height - ) + popup.showAtLocation(cursor_left, Gravity.BOTTOM or Gravity.START, x, y) } else { - popup.update( - cursor_left.x.toInt() + cursor_left.width, - page_view.height - cursor_left.y.toInt() + ReadBookConfig.durConfig.textSize.dp + popup.height, - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT - ) + popup.update(x, y, WRAP_CONTENT, WRAP_CONTENT) } } } @@ -458,9 +456,9 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo /** * 更新内容 */ - override fun upContent(position: Int) { + override fun upContent(relativePosition: Int) { launch { - page_view.upContent(position) + page_view.upContent(relativePosition) } } @@ -507,12 +505,6 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo viewModel.changeTo(book) } - override fun setPageIndex(pageIndex: Int) { - ReadBook.durPageIndex = pageIndex - ReadBook.saveRead() - ReadBook.curPageChanged() - } - override fun clickCenter() { if (BaseReadAloudService.isRun) { showReadAloudDialog() @@ -665,7 +657,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo upSystemUiVisibility() page_view.upBg() page_view.upStyle() - ChapterProvider.upStyle(ReadBookConfig.durConfig) + ChapterProvider.upStyle() if (it) { ReadBook.loadContent() } else { @@ -721,7 +713,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo Help.keepScreenOn(window, true) return } - val t = screenTimeOut - getScreenOffTime() + val t = screenTimeOut - sysScreenOffTime if (t > 0) { mHandler.removeCallbacks(keepScreenRunnable) Help.keepScreenOn(window, true) diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt index 12bbb6d8b..6dec43d12 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt @@ -10,8 +10,8 @@ import android.widget.SeekBar import androidx.core.view.isVisible import io.legado.app.App import io.legado.app.R -import io.legado.app.constant.PreferKey import io.legado.app.help.AppConfig +import io.legado.app.help.ReadBookConfig import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.buttonDisabledColor import io.legado.app.service.help.ReadBook @@ -199,9 +199,8 @@ class ReadMenu : FrameLayout { vw_menu_bg.onClick { runMenuOut() } vwNavigationBar.layoutParams = vwNavigationBar.layoutParams.apply { height = - if (context.getPrefBoolean(PreferKey.hideNavigationBar) - && Help.isNavigationBarExist(activity) - ) context.getNavigationBarHeight() + if (ReadBookConfig.hideNavigationBar && Help.isNavigationBarExist(activity)) + context.navigationBarHeight else 0 } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt index b087a1508..9b975e7e8 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt @@ -14,6 +14,7 @@ import androidx.preference.PreferenceFragmentCompat import io.legado.app.R import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.help.ReadBookConfig import io.legado.app.lib.theme.ATH import io.legado.app.ui.book.read.Help import io.legado.app.utils.getPrefBoolean @@ -92,8 +93,14 @@ class MoreConfigDialog : DialogFragment() { key: String? ) { when (key) { - PreferKey.hideStatusBar -> postEvent(EventBus.UP_CONFIG, true) - PreferKey.hideNavigationBar -> postEvent(EventBus.UP_CONFIG, true) + PreferKey.hideStatusBar -> { + ReadBookConfig.hideStatusBar = getPrefBoolean(PreferKey.hideStatusBar) + postEvent(EventBus.UP_CONFIG, true) + } + PreferKey.hideNavigationBar -> { + ReadBookConfig.hideNavigationBar = getPrefBoolean(PreferKey.hideNavigationBar) + postEvent(EventBus.UP_CONFIG, true) + } PreferKey.keepLight -> postEvent(key, true) PreferKey.textSelectAble -> postEvent(key, getPrefBoolean(key)) } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt index 1cb0715e3..c72e1a417 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/PaddingConfigDialog.kt @@ -11,6 +11,7 @@ import io.legado.app.constant.EventBus import io.legado.app.help.ReadBookConfig import io.legado.app.ui.book.read.Help import io.legado.app.utils.postEvent +import io.legado.app.utils.visible import kotlinx.android.synthetic.main.dialog_read_padding.* class PaddingConfigDialog : DialogFragment() { @@ -49,13 +50,14 @@ class PaddingConfigDialog : DialogFragment() { ReadBookConfig.save() } - private fun initData() = with(ReadBookConfig.durConfig) { + private fun initData() = with(ReadBookConfig) { //正文 dsb_padding_top.progress = paddingTop dsb_padding_bottom.progress = paddingBottom dsb_padding_left.progress = paddingLeft dsb_padding_right.progress = paddingRight //页眉 + tv_header_padding.visible(hideStatusBar) dsb_header_padding_top.progress = headerPaddingTop dsb_header_padding_bottom.progress = headerPaddingBottom dsb_header_padding_left.progress = headerPaddingLeft @@ -67,7 +69,7 @@ class PaddingConfigDialog : DialogFragment() { dsb_footer_padding_right.progress = footerPaddingRight } - private fun initView() = with(ReadBookConfig.durConfig) { + private fun initView() = with(ReadBookConfig) { //正文 dsb_padding_top.onChanged = { paddingTop = it diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt index b1f80b354..c78466569 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt @@ -11,6 +11,7 @@ import androidx.fragment.app.DialogFragment import io.legado.app.R import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.help.BookHelp import io.legado.app.help.ImageLoader import io.legado.app.help.ReadBookConfig import io.legado.app.lib.dialogs.selector @@ -19,7 +20,9 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.book.read.Help import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.widget.font.FontSelectDialog -import io.legado.app.utils.* +import io.legado.app.utils.getPrefString +import io.legado.app.utils.postEvent +import io.legado.app.utils.putPrefString import kotlinx.android.synthetic.main.activity_book_read.* import kotlinx.android.synthetic.main.dialog_read_book_style.* import org.jetbrains.anko.sdk27.listeners.onCheckedChange @@ -76,8 +79,8 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack { } private fun initData() { - cb_share_layout.isChecked = getPrefBoolean(PreferKey.shareLayout) - requireContext().getPrefInt(PreferKey.pageAnim).let { + cb_share_layout.isChecked = ReadBookConfig.shareLayout + ReadBookConfig.pageAnim.let { if (it >= 0 && it < rg_page_anim.childCount) { rg_page_anim.check(rg_page_anim[it].id) } @@ -92,14 +95,14 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack { postEvent(EventBus.UP_CONFIG, true) } tv_title_center.onClick { - ReadBookConfig.durConfig.apply { + ReadBookConfig.apply { titleCenter = !titleCenter tv_title_center.isSelected = titleCenter } postEvent(EventBus.UP_CONFIG, true) } tv_text_bold.onClick { - ReadBookConfig.durConfig.apply { + ReadBookConfig.apply { textBold = !textBold tv_text_bold.isSelected = textBold } @@ -113,7 +116,7 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack { title = getString(R.string.text_indent), items = resources.getStringArray(R.array.indent).toList() ) { _, index -> - putPrefInt(PreferKey.bodyIndent, index) + BookHelp.bodyIndentCount = index postEvent(EventBus.UP_CONFIG, true) } } @@ -125,28 +128,28 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack { } } dsb_text_size.onChanged = { - ReadBookConfig.durConfig.textSize = it + 5 + ReadBookConfig.textSize = it + 5 postEvent(EventBus.UP_CONFIG, true) } dsb_text_letter_spacing.onChanged = { - ReadBookConfig.durConfig.letterSpacing = (it - 50) / 100f + ReadBookConfig.letterSpacing = (it - 50) / 100f postEvent(EventBus.UP_CONFIG, true) } dsb_line_size.onChanged = { - ReadBookConfig.durConfig.lineSpacingExtra = it + ReadBookConfig.lineSpacingExtra = it postEvent(EventBus.UP_CONFIG, true) } dsb_paragraph_spacing.onChanged = { - ReadBookConfig.durConfig.paragraphSpacing = it + ReadBookConfig.paragraphSpacing = it postEvent(EventBus.UP_CONFIG, true) } rg_page_anim.onCheckedChange { _, checkedId -> for (i in 0 until rg_page_anim.childCount) { if (checkedId == rg_page_anim[i].id) { - requireContext().putPrefInt(PreferKey.pageAnim, i) + ReadBookConfig.pageAnim = i val activity = activity if (activity is ReadBookActivity) { - activity.page_view.upPageAnim(i) + activity.page_view.upPageAnim() } break } @@ -154,7 +157,9 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack { } cb_share_layout.onCheckedChangeListener = { checkBox, isChecked -> if (checkBox.isPressed) { - putPrefBoolean(PreferKey.shareLayout, isChecked) + ReadBookConfig.shareLayout = isChecked + upStyle() + postEvent(EventBus.UP_CONFIG, true) } } bg0.onClick { changeBg(0) } @@ -190,7 +195,7 @@ class ReadStyleDialog : DialogFragment(), FontSelectDialog.CallBack { } private fun upStyle() { - ReadBookConfig.durConfig.let { + ReadBookConfig.let { tv_title_center.isSelected = it.titleCenter tv_text_bold.isSelected = it.textBold dsb_text_size.progress = it.textSize - 5 diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt index ba9b23a44..f2046ac4b 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt @@ -28,10 +28,9 @@ import io.legado.app.lib.dialogs.cancelButton import io.legado.app.lib.dialogs.customView import io.legado.app.lib.dialogs.okButton import io.legado.app.model.localBook.AnalyzeTxtFile +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint -import io.legado.app.utils.getVerticalDivider import kotlinx.android.synthetic.main.dialog_toc_regex.* -import kotlinx.android.synthetic.main.dialog_toc_regex_edit.* import kotlinx.android.synthetic.main.dialog_toc_regex_edit.view.* import kotlinx.android.synthetic.main.item_toc_regex.view.* import kotlinx.coroutines.Dispatchers.IO @@ -76,7 +75,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { private fun initView() { adapter = TocRegexAdapter(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter val itemTouchCallback = ItemTouchCallback() itemTouchCallback.onItemTouchCallbackListener = adapter @@ -150,7 +149,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { } } okButton { - rootView?.let { + rootView?.apply { tocRule.name = tv_rule_name.text.toString() tocRule.rule = tv_rule_regex.text.toString() saveRule(tocRule, rule) diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt index 8a4a46e06..74136ba5c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt @@ -10,7 +10,10 @@ import io.legado.app.constant.PreferKey import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp import io.legado.app.help.ReadBookConfig -import io.legado.app.ui.book.read.page.entities.* +import io.legado.app.ui.book.read.page.entities.TextChapter +import io.legado.app.ui.book.read.page.entities.TextChar +import io.legado.app.ui.book.read.page.entities.TextLine +import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.utils.dp import io.legado.app.utils.getPrefString import io.legado.app.utils.removePref @@ -20,10 +23,10 @@ import io.legado.app.utils.removePref object ChapterProvider { var viewWidth = 0 var viewHeight = 0 - private var visibleWidth = 0 - private var visibleHeight = 0 - private var paddingLeft = 0 - private var paddingTop = 0 + var visibleWidth = 0 + var visibleHeight = 0 + var paddingLeft = 0 + var paddingTop = 0 private var lineSpacingExtra = 0f private var paragraphSpacing = 0 var typeface: Typeface = Typeface.SANS_SERIF @@ -32,7 +35,7 @@ object ChapterProvider { private var bodyIndent = BookHelp.bodyIndent init { - upStyle(ReadBookConfig.durConfig) + upStyle() } /** @@ -116,12 +119,12 @@ object ChapterProvider { Layout.Alignment.ALIGN_NORMAL, 1f, lineSpacingExtra, true ) for (lineIndex in 0 until layout.lineCount) { + textPages.last().height = durY durY = durY + layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex) val textLine = TextLine(isTitle = true) if (durY < visibleHeight) { textPages.last().textLines.add(textLine) } else { - textPages.last().height = durY textPages.last().text = stringBuilder.toString() stringBuilder.clear() pageLines.add(textPages.last().textLines.size) @@ -131,10 +134,11 @@ object ChapterProvider { textPages.add(TextPage()) textPages.last().textLines.add(textLine) } - textLine.lineBottom = (paddingTop + durY - - (layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))).toFloat() textLine.lineTop = (paddingTop + durY - (layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex))).toFloat() + textLine.lineBase = (paddingTop + durY - + (layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))).toFloat() + textLine.lineBottom = textLine.lineBase + titlePaint.fontMetrics.descent val words = title.substring(layout.getLineStart(lineIndex), layout.getLineEnd(lineIndex)) stringBuilder.append(words) @@ -150,8 +154,8 @@ object ChapterProvider { val x1 = if (i != words.lastIndex) (x + cw + d) else (x + cw) val textChar = TextChar( charData = char, - leftBottomPosition = TextPoint(paddingLeft + x, textLine.lineBottom), - rightTopPosition = TextPoint(paddingLeft + x1, textLine.lineTop) + start = paddingLeft + x, + end = paddingLeft + x1 ) textLine.textChars.add(textChar) x = x1 @@ -160,7 +164,7 @@ object ChapterProvider { //最后一行 textLine.text = "$words\n" stringBuilder.append("\n") - var x = if (ReadBookConfig.durConfig.titleCenter) + var x = if (ReadBookConfig.titleCenter) (visibleWidth - layout.getLineMax(lineIndex)) / 2 else 0f for (i in words.indices) { @@ -169,14 +173,13 @@ object ChapterProvider { val x1 = x + cw val textChar = TextChar( charData = char, - leftBottomPosition = TextPoint(paddingLeft + x, textLine.lineBottom), - rightTopPosition = TextPoint(paddingLeft + x1, textLine.lineTop) + start = paddingLeft + x, + end = paddingLeft + x1 ) textLine.textChars.add(textChar) x = x1 } } - textLine.lineBottom = textLine.lineBottom + titlePaint.fontMetrics.descent } durY += paragraphSpacing return durY @@ -199,12 +202,12 @@ object ChapterProvider { Layout.Alignment.ALIGN_NORMAL, 1f, lineSpacingExtra, true ) for (lineIndex in 0 until layout.lineCount) { - val textLine = TextLine(isTitle = false) + textPages.last().height = durY durY = durY + layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex) + val textLine = TextLine() if (durY < visibleHeight) { textPages.last().textLines.add(textLine) } else { - textPages.last().height = durY textPages.last().text = stringBuilder.toString() stringBuilder.clear() pageLines.add(textPages.last().textLines.size) @@ -214,10 +217,11 @@ object ChapterProvider { textPages.add(TextPage()) textPages.last().textLines.add(textLine) } - textLine.lineBottom = (paddingTop + durY - - (layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))).toFloat() textLine.lineTop = (paddingTop + durY - (layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex))).toFloat() + textLine.lineBase = (paddingTop + durY - + (layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))).toFloat() + textLine.lineBottom = textLine.lineBase + contentPaint.fontMetrics.descent var words = text.substring(layout.getLineStart(lineIndex), layout.getLineEnd(lineIndex)) stringBuilder.append(words) @@ -231,8 +235,8 @@ object ChapterProvider { val x1 = x + icw val textChar = TextChar( charData = bodyIndent[i].toString(), - leftBottomPosition = TextPoint(paddingLeft + x, textLine.lineBottom), - rightTopPosition = TextPoint(paddingLeft + x1, textLine.lineTop) + start = paddingLeft + x, + end = paddingLeft + x1 ) textLine.textChars.add(textChar) x = x1 @@ -246,8 +250,8 @@ object ChapterProvider { val x1 = if (i != words.lastIndex) x + cw + d else x + cw val textChar1 = TextChar( charData = char, - leftBottomPosition = TextPoint(paddingLeft + x, textLine.lineBottom), - rightTopPosition = TextPoint(paddingLeft + x1, textLine.lineTop) + start = paddingLeft + x, + end = paddingLeft + x1 ) textLine.textChars.add(textChar1) x = x1 @@ -263,8 +267,8 @@ object ChapterProvider { val x1 = x + cw val textChar = TextChar( charData = char, - leftBottomPosition = TextPoint(paddingLeft + x, textLine.lineBottom), - rightTopPosition = TextPoint(paddingLeft + x1, textLine.lineTop) + start = paddingLeft + x, + end = paddingLeft + x1 ) textLine.textChars.add(textChar) x = x1 @@ -280,14 +284,13 @@ object ChapterProvider { val x1 = if (i != words.lastIndex) x + cw + d else x + cw val textChar = TextChar( charData = char, - leftBottomPosition = TextPoint(paddingLeft + x, textLine.lineBottom), - rightTopPosition = TextPoint(paddingLeft + x1, textLine.lineTop) + start = paddingLeft + x, + end = paddingLeft + x1 ) textLine.textChars.add(textChar) x = x1 } } - textLine.lineBottom = textLine.lineBottom + contentPaint.fontMetrics.descent } durY += paragraphSpacing return durY @@ -297,7 +300,7 @@ object ChapterProvider { /** * 更新样式 */ - fun upStyle(config: ReadBookConfig.Config) { + fun upStyle() { typeface = try { val fontPath = App.INSTANCE.getPrefString(PreferKey.readBookFont) if (!TextUtils.isEmpty(fontPath)) { @@ -311,34 +314,34 @@ object ChapterProvider { } //标题 titlePaint.isAntiAlias = true - titlePaint.color = config.textColor() - titlePaint.letterSpacing = config.letterSpacing + titlePaint.color = ReadBookConfig.durConfig.textColor() + titlePaint.letterSpacing = ReadBookConfig.letterSpacing titlePaint.typeface = Typeface.create(typeface, Typeface.BOLD) //正文 contentPaint.isAntiAlias = true - contentPaint.color = config.textColor() - contentPaint.letterSpacing = config.letterSpacing - val bold = if (config.textBold) Typeface.BOLD else Typeface.NORMAL + contentPaint.color = ReadBookConfig.durConfig.textColor() + contentPaint.letterSpacing = ReadBookConfig.letterSpacing + val bold = if (ReadBookConfig.textBold) Typeface.BOLD else Typeface.NORMAL contentPaint.typeface = Typeface.create(typeface, bold) //间距 - lineSpacingExtra = config.lineSpacingExtra.dp.toFloat() - paragraphSpacing = config.paragraphSpacing.dp - titlePaint.textSize = (config.textSize + 2).dp.toFloat() - contentPaint.textSize = config.textSize.dp.toFloat() + lineSpacingExtra = ReadBookConfig.lineSpacingExtra.dp.toFloat() + paragraphSpacing = ReadBookConfig.paragraphSpacing.dp + titlePaint.textSize = (ReadBookConfig.textSize + 2).dp.toFloat() + contentPaint.textSize = ReadBookConfig.textSize.dp.toFloat() bodyIndent = BookHelp.bodyIndent - upSize(config) + upSize() } /** * 更新View尺寸 */ - fun upSize(config: ReadBookConfig.Config) { - paddingLeft = config.paddingLeft.dp - paddingTop = config.paddingTop.dp - visibleWidth = viewWidth - paddingLeft - config.paddingRight.dp - visibleHeight = viewHeight - paddingTop - config.paddingBottom.dp + fun upSize() { + paddingLeft = ReadBookConfig.paddingLeft.dp + paddingTop = ReadBookConfig.paddingTop.dp + visibleWidth = viewWidth - paddingLeft - ReadBookConfig.paddingRight.dp + visibleHeight = viewHeight - paddingTop - ReadBookConfig.paddingBottom.dp } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt index eeae9d33b..7d2262824 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt @@ -3,14 +3,13 @@ package io.legado.app.ui.book.read.page import android.content.Context import android.graphics.Canvas import android.graphics.Paint -import android.text.Layout -import android.text.StaticLayout import android.util.AttributeSet import android.view.View import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.help.ReadBookConfig import io.legado.app.lib.theme.accentColor +import io.legado.app.ui.book.read.page.entities.TextChar import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.utils.activity import io.legado.app.utils.getCompatColor @@ -18,6 +17,8 @@ import io.legado.app.utils.getPrefBoolean class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, attrs) { + var selectAble = context.getPrefBoolean(PreferKey.textSelectAble) + var upView: ((TextPage) -> Unit)? = null private val selectedPaint by lazy { Paint().apply { color = context.getCompatColor(R.color.btn_bg_press_2) @@ -25,7 +26,6 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at } } private var callBack: CallBack - var selectAble = context.getPrefBoolean(PreferKey.textSelectAble) private var selectLineStart = 0 private var selectCharStart = 0 private var selectLineEnd = 0 @@ -36,7 +36,6 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at private val maxScrollOffset = 100f private var pageOffset = 0f private var linePos = 0 - private var isLastPage = false init { callBack = activity as CallBack @@ -51,70 +50,105 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) - ReadBookConfig.durConfig.let { - ChapterProvider.viewWidth = w - ChapterProvider.viewHeight = h - ChapterProvider.upSize(ReadBookConfig.durConfig) - } + ChapterProvider.viewWidth = w + ChapterProvider.viewHeight = h + ChapterProvider.upSize() + textPage.format() } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) - if (textPage.textLines.isEmpty()) { - drawMsg(canvas, textPage.text) + if (ReadBookConfig.isScroll) { + drawScrollPage(canvas) } else { drawHorizontalPage(canvas) } } - @Suppress("DEPRECATION") - private fun drawMsg(canvas: Canvas, msg: String) { - val layout = StaticLayout( - msg, ChapterProvider.contentPaint, width, - Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false - ) - val y = (height - layout.height) / 2f - for (lineIndex in 0 until layout.lineCount) { - val x = (width - layout.getLineMax(lineIndex)) / 2 - val words = - msg.substring(layout.getLineStart(lineIndex), layout.getLineEnd(lineIndex)) - canvas.drawText(words, x, y, ChapterProvider.contentPaint) + private fun drawHorizontalPage(canvas: Canvas) { + textPage.textLines.forEach { textLine -> + drawChars( + canvas, + textLine.textChars, + textLine.lineTop, + textLine.lineBase, + textLine.lineBottom, + textLine.isTitle, + textLine.isReadAloud + ) } } - private fun drawHorizontalPage(canvas: Canvas) { + private fun drawScrollPage(canvas: Canvas) { + val mPageOffset = pageOffset textPage.textLines.forEach { textLine -> - val textPaint = if (textLine.isTitle) { - ChapterProvider.titlePaint - } else { - ChapterProvider.contentPaint - } - textPaint.color = if (textLine.isReadAloud) { - context.accentColor - } else { - ReadBookConfig.durConfig.textColor() - } - textLine.textChars.forEach { - canvas.drawText( - it.charData, - it.leftBottomPosition.x, - it.leftBottomPosition.y, - textPaint - ) - if (it.selected) { - canvas.drawRect( - it.leftBottomPosition.x, - textLine.lineTop, - it.rightTopPosition.x, - textLine.lineBottom, - selectedPaint - ) - } + val lineTop = textLine.lineTop + mPageOffset + val lineBase = textLine.lineBase + mPageOffset + val lineBottom = textLine.lineBottom + mPageOffset + drawChars( + canvas, + textLine.textChars, + lineTop, + lineBase, + lineBottom, + textLine.isTitle, + textLine.isReadAloud + ) + } + pageFactory.nextPage?.textLines?.forEach { textLine -> + val yPy = mPageOffset + textPage.height - ChapterProvider.paddingTop + val lineTop = textLine.lineTop + yPy + val lineBase = textLine.lineBase + yPy + val lineBottom = textLine.lineBottom + yPy + drawChars( + canvas, + textLine.textChars, + lineTop, + lineBase, + lineBottom, + textLine.isTitle, + textLine.isReadAloud + ) + } + pageFactory.prevPage?.textLines?.forEach { textLine -> + val yPy = mPageOffset + ChapterProvider.paddingTop + val lineTop = -textLine.lineTop + yPy + val lineBase = -textLine.lineBase + yPy + val lineBottom = -textLine.lineBottom + yPy + drawChars( + canvas, + textLine.textChars, + lineTop, + lineBase, + lineBottom, + textLine.isTitle, + textLine.isReadAloud + ) + } + } + + private fun drawChars( + canvas: Canvas, + textChars: List, + lineTop: Float, + lineBase: Float, + lineBottom: Float, + isTitle: Boolean, + isReadAloud: Boolean + ) { + val textPaint = if (isTitle) ChapterProvider.titlePaint else ChapterProvider.contentPaint + textPaint.color = + if (isReadAloud) context.accentColor else ReadBookConfig.durConfig.textColor() + textChars.forEach { + canvas.drawText(it.charData, it.start, lineBase, textPaint) + if (it.selected) { + canvas.drawRect(it.start, lineTop, it.end, lineBottom, selectedPaint) } } } fun onScroll(mOffset: Float) { + if (mOffset == 0f) return var offset = mOffset if (offset > maxScrollOffset) { offset = maxScrollOffset @@ -122,78 +156,56 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at offset = -maxScrollOffset } - if (!isLastPage || offset < 0) { - pageOffset += offset - isLastPage = false - } - // 首页 - if (pageOffset < 0 && !pageFactory.hasPrev()) { - pageOffset = 0f - } - - val cHeight = if (textPage.height > 0) textPage.height else height - if (offset > 0 && pageOffset > cHeight) { - + pageOffset += offset + if (pageOffset > 0) { + pageFactory.moveToPrev() + textPage = pageFactory.currentPage ?: TextPage().format() + pageOffset -= textPage.height + upView?.invoke(textPage) + } else if (pageOffset < -textPage.height) { + pageOffset += textPage.height + pageFactory.moveToNext() + textPage = pageFactory.currentPage ?: TextPage().format() + upView?.invoke(textPage) } + invalidate() } fun resetPageOffset() { pageOffset = 0f linePos = 0 - isLastPage = false } - private fun switchToPageOffset(offset: Int) { - when (offset) { - 1 -> { - - } - -1 -> { - - } - } - } - - fun selectText(x: Float, y: Float): Boolean { + fun selectText(x: Float, y: Float, select: (lineIndex: Int, charIndex: Int) -> Unit) { for ((lineIndex, textLine) in textPage.textLines.withIndex()) { if (y > textLine.lineTop && y < textLine.lineBottom) { for ((charIndex, textChar) in textLine.textChars.withIndex()) { - if (x > textChar.leftBottomPosition.x && x < textChar.rightTopPosition.x) { + if (x > textChar.start && x < textChar.end) { textChar.selected = true invalidate() selectLineStart = lineIndex selectCharStart = charIndex selectLineEnd = lineIndex selectCharEnd = charIndex - upSelectedStart( - textChar.leftBottomPosition.x, - textChar.leftBottomPosition.y - ) - upSelectedEnd( - textChar.rightTopPosition.x, - textChar.leftBottomPosition.y - ) - return true + upSelectedStart(textChar.start, textLine.lineBottom) + upSelectedEnd(textChar.end, textLine.lineBottom) + select(lineIndex, charIndex) } } break } } - return false } fun selectStartMove(x: Float, y: Float) { for ((lineIndex, textLine) in textPage.textLines.withIndex()) { if (y > textLine.lineTop && y < textLine.lineBottom) { for ((charIndex, textChar) in textLine.textChars.withIndex()) { - if (x > textChar.leftBottomPosition.x && x < textChar.rightTopPosition.x) { + if (x > textChar.start && x < textChar.end) { if (selectLineStart != lineIndex || selectCharStart != charIndex) { selectLineStart = lineIndex selectCharStart = charIndex - upSelectedStart( - textChar.leftBottomPosition.x, - textChar.leftBottomPosition.y - ) + upSelectedStart(textChar.start, textLine.lineBottom) upSelectChars(textPage) } break @@ -204,18 +216,24 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at } } + fun selectStartMoveIndex(lineIndex: Int, charIndex: Int) { + selectLineStart = lineIndex + selectCharStart = charIndex + val textLine = textPage.textLines[lineIndex] + val textChar = textLine.textChars[charIndex] + upSelectedStart(textChar.start, textLine.lineBottom) + upSelectChars(textPage) + } + fun selectEndMove(x: Float, y: Float) { for ((lineIndex, textLine) in textPage.textLines.withIndex()) { if (y > textLine.lineTop && y < textLine.lineBottom) { for ((charIndex, textChar) in textLine.textChars.withIndex()) { - if (x > textChar.leftBottomPosition.x && x < textChar.rightTopPosition.x) { + if (x > textChar.start && x < textChar.end) { if (selectLineEnd != lineIndex || selectCharEnd != charIndex) { selectLineEnd = lineIndex selectCharEnd = charIndex - upSelectedEnd( - textChar.rightTopPosition.x, - textChar.leftBottomPosition.y - ) + upSelectedEnd(textChar.end, textLine.lineBottom) upSelectChars(textPage) } break @@ -226,6 +244,15 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at } } + fun selectEndMoveIndex(lineIndex: Int, charIndex: Int) { + selectLineEnd = lineIndex + selectCharEnd = charIndex + val textLine = textPage.textLines[lineIndex] + val textChar = textLine.textChars[charIndex] + upSelectedEnd(textChar.end, textLine.lineBottom) + upSelectChars(textPage) + } + private fun upSelectChars(textPage: TextPage) { for ((lineIndex, textLine) in textPage.textLines.withIndex()) { for ((charIndex, textChar) in textLine.textChars.withIndex()) { diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt index abb2b82c4..512f778a7 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt @@ -7,7 +7,6 @@ import android.view.MotionEvent import android.widget.FrameLayout import io.legado.app.R import io.legado.app.constant.AppConst.TIME_FORMAT -import io.legado.app.constant.PreferKey import io.legado.app.help.ReadBookConfig import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.utils.* @@ -25,18 +24,23 @@ class ContentView(context: Context) : FrameLayout(context) { upStyle() upTime() + content_text_view.upView = { + tv_bottom_left.text = it.title + pageSize = it.pageSize + setPageIndex(it.index) + } } fun upStyle() { - ReadBookConfig.durConfig.apply { + ReadBookConfig.apply { tv_top_left.typeface = ChapterProvider.typeface tv_top_right.typeface = ChapterProvider.typeface tv_bottom_left.typeface = ChapterProvider.typeface tv_bottom_right.typeface = ChapterProvider.typeface //显示状态栏时隐藏header - if (context.getPrefBoolean(PreferKey.hideStatusBar, false)) { + if (hideStatusBar) { ll_header.layoutParams = - ll_header.layoutParams.apply { height = context.getStatusBarHeight() } + ll_header.layoutParams.apply { height = context.statusBarHeight } ll_header.setPadding( headerPaddingLeft.dp, headerPaddingTop.dp, @@ -47,7 +51,7 @@ class ContentView(context: Context) : FrameLayout(context) { page_panel.setPadding(0, 0, 0, 0) } else { ll_header.gone() - page_panel.setPadding(0, context.getStatusBarHeight(), 0, 0) + page_panel.setPadding(0, context.statusBarHeight, 0, 0) } content_text_view.setPadding( paddingLeft.dp, @@ -61,7 +65,7 @@ class ContentView(context: Context) : FrameLayout(context) { footerPaddingRight.dp, footerPaddingBottom.dp ) - textColor().let { + durConfig.textColor().let { tv_top_left.setTextColor(it) tv_top_right.setTextColor(it) tv_bottom_left.setTextColor(it) @@ -72,10 +76,10 @@ class ContentView(context: Context) : FrameLayout(context) { val headerHeight: Int get() { - return if (context.getPrefBoolean(PreferKey.hideStatusBar, false)) { + return if (ReadBookConfig.hideStatusBar) { ll_header.height } else { - context.getStatusBarHeight() + context.statusBarHeight } } @@ -93,10 +97,11 @@ class ContentView(context: Context) : FrameLayout(context) { fun setContent(textPage: TextPage?) { if (textPage != null) { - content_text_view.setContent(textPage) tv_bottom_left.text = textPage.title pageSize = textPage.pageSize setPageIndex(textPage.index) + content_text_view.resetPageOffset() + content_text_view.setContent(textPage) } } @@ -115,19 +120,27 @@ class ContentView(context: Context) : FrameLayout(context) { content_text_view.selectAble = selectAble } - fun selectText(e: MotionEvent): Boolean { + fun selectText(e: MotionEvent, select: (lineIndex: Int, charIndex: Int) -> Unit) { val y = e.y - headerHeight - return content_text_view.selectText(e.x, y) + return content_text_view.selectText(e.x, y, select) } fun selectStartMove(x: Float, y: Float) { content_text_view.selectStartMove(x, y - headerHeight) } + fun selectStartMoveIndex(lineIndex: Int, charIndex: Int) { + content_text_view.selectStartMoveIndex(lineIndex, charIndex) + } + fun selectEndMove(x: Float, y: Float) { content_text_view.selectEndMove(x, y - headerHeight) } + fun selectEndMoveIndex(lineIndex: Int, charIndex: Int) { + content_text_view.selectEndMoveIndex(lineIndex, charIndex) + } + fun cancelSelect() { content_text_view.cancelSelect() } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt b/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt index ed223a4cf..106e2e4db 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt @@ -1,15 +1,11 @@ package io.legado.app.ui.book.read.page +import io.legado.app.service.help.ReadBook import io.legado.app.ui.book.read.page.entities.TextChapter interface DataSource { - val isScrollDelegate: Boolean - val pageIndex: Int - - fun setPageIndex(pageIndex: Int) - - fun getChapterPosition(): Int + val pageIndex: Int get() = ReadBook.durChapterPos() fun getCurrentChapter(): TextChapter? @@ -20,5 +16,4 @@ interface DataSource { fun hasNextChapter(): Boolean fun hasPrevChapter(): Boolean - } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageFactory.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageFactory.kt index 6f39f2992..db504b6f4 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/PageFactory.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageFactory.kt @@ -8,13 +8,13 @@ abstract class PageFactory(protected val dataSource: DataSource) { abstract fun moveToNext():Boolean - abstract fun moveToPrevious(): Boolean + abstract fun moveToPrev(): Boolean - abstract fun nextPage(): DATA? + abstract val nextPage: DATA? - abstract fun previousPage(): DATA? + abstract val prevPage: DATA? - abstract fun currentPage(): DATA? + abstract val currentPage: DATA? abstract fun hasNext(): Boolean diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt index a0c6c962a..3009af02e 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt @@ -6,13 +6,11 @@ import android.graphics.Canvas import android.util.AttributeSet import android.view.MotionEvent import android.widget.FrameLayout -import io.legado.app.constant.PreferKey import io.legado.app.help.ReadBookConfig import io.legado.app.service.help.ReadBook import io.legado.app.ui.book.read.page.delegate.* import io.legado.app.ui.book.read.page.entities.TextChapter import io.legado.app.utils.activity -import io.legado.app.utils.getPrefInt class PageView(context: Context, attrs: AttributeSet) : FrameLayout(context, attrs), @@ -37,7 +35,7 @@ class PageView(context: Context, attrs: AttributeSet) : upBg() setWillNotDraw(false) pageFactory = TextPageFactory(this) - upPageAnim(context.getPrefInt(PreferKey.pageAnim)) + upPageAnim() } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { @@ -64,8 +62,9 @@ class PageView(context: Context, attrs: AttributeSet) : @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent): Boolean { + pageDelegate?.onTouch(event) callBack.screenOffTimerStart() - return pageDelegate?.onTouch(event) ?: super.onTouchEvent(event) + return true } fun onDestroy() { @@ -76,7 +75,7 @@ class PageView(context: Context, attrs: AttributeSet) : fun fillPage(direction: PageDelegate.Direction) { when (direction) { PageDelegate.Direction.PREV -> { - pageFactory.moveToPrevious() + pageFactory.moveToPrev() upContent() } PageDelegate.Direction.NEXT -> { @@ -87,10 +86,10 @@ class PageView(context: Context, attrs: AttributeSet) : } } - fun upPageAnim(pageAnim: Int) { + fun upPageAnim() { pageDelegate?.onDestroy() pageDelegate = null - pageDelegate = when (pageAnim) { + pageDelegate = when (ReadBookConfig.pageAnim) { 0 -> CoverPageDelegate(this) 1 -> SlidePageDelegate(this) 2 -> SimulationPageDelegate(this) @@ -100,15 +99,17 @@ class PageView(context: Context, attrs: AttributeSet) : upContent() } - fun upContent(position: Int = 0) { - pageFactory.let { - when (position) { - -1 -> prevPage.setContent(it.previousPage()) - 1 -> nextPage.setContent(it.nextPage()) + fun upContent(relativePosition: Int = 0) { + if (ReadBookConfig.isScroll) { + curPage.setContent(pageFactory.currentPage) + } else { + when (relativePosition) { + -1 -> prevPage.setContent(pageFactory.prevPage) + 1 -> nextPage.setContent(pageFactory.nextPage) else -> { - curPage.setContent(it.currentPage()) - nextPage.setContent(it.nextPage()) - prevPage.setContent(it.previousPage()) + curPage.setContent(pageFactory.currentPage) + nextPage.setContent(pageFactory.nextPage) + prevPage.setContent(pageFactory.prevPage) } } } @@ -163,20 +164,6 @@ class PageView(context: Context, attrs: AttributeSet) : nextPage.upBattery(battery) } - override val isScrollDelegate: Boolean - get() = pageDelegate is ScrollPageDelegate - - override val pageIndex: Int - get() = ReadBook.durChapterPos() - - override fun setPageIndex(pageIndex: Int) { - callBack.setPageIndex(pageIndex) - } - - override fun getChapterPosition(): Int { - return ReadBook.durChapterIndex - } - override fun getCurrentChapter(): TextChapter? { return if (callBack.isInitFinish) ReadBook.textChapter(0) else null } @@ -198,19 +185,8 @@ class PageView(context: Context, attrs: AttributeSet) : } interface CallBack { - val isInitFinish: Boolean - - /** - * 保存页数 - */ - fun setPageIndex(pageIndex: Int) - - /** - * 点击屏幕中间 - */ fun clickCenter() - fun screenOffTimerStart() } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt b/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt index 018f75bab..307423955 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt @@ -14,63 +14,65 @@ class TextPageFactory(dataSource: DataSource) : PageFactory(dataSource } override fun moveToFirst() { - dataSource.setPageIndex(0) + ReadBook.setPageIndex(0) } override fun moveToLast() = with(dataSource) { getCurrentChapter()?.let { if (it.pageSize() == 0) { - setPageIndex(0) + ReadBook.setPageIndex(0) } else { - setPageIndex(it.pageSize().minus(1)) + ReadBook.setPageIndex(it.pageSize().minus(1)) } - } ?: setPageIndex(0) + } ?: ReadBook.setPageIndex(0) } override fun moveToNext(): Boolean = with(dataSource) { return if (hasNext()) { - if (getCurrentChapter()?.isLastIndex(pageIndex) == true - ) { + if (getCurrentChapter()?.isLastIndex(pageIndex) == true) { ReadBook.moveToNextChapter(false) } else { - setPageIndex(pageIndex.plus(1)) + ReadBook.setPageIndex(pageIndex.plus(1)) } true } else false } - override fun moveToPrevious(): Boolean = with(dataSource) { + override fun moveToPrev(): Boolean = with(dataSource) { return if (hasPrev()) { if (pageIndex <= 0) { ReadBook.moveToPrevChapter(false) } else { - setPageIndex(pageIndex.minus(1)) + ReadBook.setPageIndex(pageIndex.minus(1)) } true } else false } - override fun currentPage(): TextPage? = with(dataSource) { - return getCurrentChapter()?.page(pageIndex) - } + override val currentPage: TextPage? + get() = with(dataSource) { + return getCurrentChapter()?.page(pageIndex) + } - override fun nextPage(): TextPage? = with(dataSource) { - getCurrentChapter()?.let { - if (pageIndex < it.pageSize() - 1) { - return getCurrentChapter()?.page(pageIndex + 1)?.removePageAloudSpan() + override val nextPage: TextPage? + get() = with(dataSource) { + getCurrentChapter()?.let { + if (pageIndex < it.pageSize() - 1) { + return getCurrentChapter()?.page(pageIndex + 1)?.removePageAloudSpan() + } } + return getNextChapter()?.page(0)?.removePageAloudSpan() } - return getNextChapter()?.page(0)?.removePageAloudSpan() - } - override fun previousPage(): TextPage? = with(dataSource) { - if (pageIndex > 0) { - return getCurrentChapter()?.page(pageIndex - 1)?.removePageAloudSpan() + override val prevPage: TextPage? + get() = with(dataSource) { + if (pageIndex > 0) { + return getCurrentChapter()?.page(pageIndex - 1)?.removePageAloudSpan() + } + return getPreviousChapter()?.lastPage()?.removePageAloudSpan() } - return getPreviousChapter()?.lastPage()?.removePageAloudSpan() - } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/HorizontalPageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/HorizontalPageDelegate.kt index f129d41ff..263e2029d 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/HorizontalPageDelegate.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/HorizontalPageDelegate.kt @@ -6,19 +6,29 @@ import kotlin.math.abs abstract class HorizontalPageDelegate(pageView: PageView) : PageDelegate(pageView) { - override fun onScroll( - e1: MotionEvent, - e2: MotionEvent, - distanceX: Float, - distanceY: Float - ): Boolean { + override fun onTouch(event: MotionEvent) { + when (event.action) { + MotionEvent.ACTION_MOVE -> { + if (isTextSelected) { + selectText(event) + } else { + onScroll(event) + } + } + } + super.onTouch(event) + } + + private fun onScroll(event: MotionEvent) { + //判断是否移动了 if (!isMoved) { - if (abs(distanceX) > abs(distanceY)) { - if (distanceX < 0) { + isMoved = abs(startX - event.x) > slop || abs(startY - event.y) > slop + if (isMoved) { + if (event.x - startX > 0) { //如果上一页不存在 if (!hasPrev()) { noNext = true - return true + return } setDirection(Direction.PREV) setBitmap() @@ -26,21 +36,19 @@ abstract class HorizontalPageDelegate(pageView: PageView) : PageDelegate(pageVie //如果不存在表示没有下一页了 if (!hasNext()) { noNext = true - return true + return } setDirection(Direction.NEXT) setBitmap() } - isMoved = true } } if (isMoved) { - isCancel = if (mDirection == Direction.NEXT) distanceX < 0 else distanceX > 0 + isCancel = if (mDirection == Direction.NEXT) touchX > lastX else touchX < lastX isRunning = true //设置触摸点 - setTouchPoint(e2.x, e2.y) + setTouchPoint(event.x, event.y) } - return isMoved } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt index 2a90c79f1..234ce8097 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt @@ -6,15 +6,14 @@ import android.graphics.Canvas import android.graphics.RectF import android.view.GestureDetector import android.view.MotionEvent +import android.view.ViewConfiguration +import android.view.animation.DecelerateInterpolator import android.widget.Scroller import androidx.annotation.CallSuper -import androidx.interpolator.view.animation.FastOutLinearInInterpolator import com.google.android.material.snackbar.Snackbar -import io.legado.app.constant.PreferKey import io.legado.app.help.AppConfig import io.legado.app.ui.book.read.page.ContentView import io.legado.app.ui.book.read.page.PageView -import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.screenshot import kotlin.math.abs @@ -25,44 +24,36 @@ abstract class PageDelegate(protected val pageView: PageView) : pageView.width * 0.66f, pageView.height * 0.66f ) protected val context: Context = pageView.context + protected val slop = ViewConfiguration.get(context).scaledTouchSlop //起始点 protected var startX: Float = 0f protected var startY: Float = 0f //上一个触碰点 + protected var lastX: Float = 0f protected var lastY: Float = 0f //触碰点 protected var touchX: Float = 0f protected var touchY: Float = 0f - protected val nextPage: ContentView - get() = pageView.nextPage - - protected val curPage: ContentView - get() = pageView.curPage - - protected val prevPage: ContentView - get() = pageView.prevPage + protected val nextPage: ContentView get() = pageView.nextPage + protected val curPage: ContentView get() = pageView.curPage + protected val prevPage: ContentView get() = pageView.prevPage protected var bitmap: Bitmap? = null protected var viewWidth: Int = pageView.width protected var viewHeight: Int = pageView.height - //textView在顶端或低端 - protected var atTop: Boolean = false - protected var atBottom: Boolean = false private val snackBar: Snackbar by lazy { Snackbar.make(pageView, "", Snackbar.LENGTH_SHORT) } private val scroller: Scroller by lazy { - Scroller(pageView.context, FastOutLinearInInterpolator()) + Scroller(pageView.context, DecelerateInterpolator()) } private val detector: GestureDetector by lazy { - GestureDetector(pageView.context, this).apply { - setIsLongpressEnabled(context.getPrefBoolean(PreferKey.textSelectAble)) - } + GestureDetector(pageView.context, this) } var isMoved = false @@ -74,26 +65,32 @@ abstract class PageDelegate(protected val pageView: PageView) : var isRunning = false var isStarted = false var isTextSelected = false + var selectedOnDown = false + + var firstLineIndex: Int = 0 + var firstCharIndex: Int = 0 open fun setStartPoint(x: Float, y: Float, invalidate: Boolean = true) { startX = x startY = y + lastX = x lastY = y touchX = x touchY = y if (invalidate) { - invalidate() + pageView.invalidate() } } open fun setTouchPoint(x: Float, y: Float, invalidate: Boolean = true) { + lastX = touchX lastY = touchY touchX = x touchY = y if (invalidate) { - invalidate() + pageView.invalidate() } onScroll() @@ -103,10 +100,6 @@ abstract class PageDelegate(protected val pageView: PageView) : detector.setIsLongpressEnabled(selectAble) } - protected fun invalidate() { - pageView.invalidate() - } - open fun fling( startX: Int, startY: Int, velocityX: Int, velocityY: Int, minX: Int, maxX: Int, minY: Int, maxY: Int @@ -114,7 +107,7 @@ abstract class PageDelegate(protected val pageView: PageView) : scroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY) isRunning = true isStarted = true - invalidate() + pageView.invalidate() } protected fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) { @@ -127,13 +120,13 @@ abstract class PageDelegate(protected val pageView: PageView) : ) isRunning = true isStarted = true - invalidate() + pageView.invalidate() } private fun stopScroll() { isRunning = false isStarted = false - invalidate() + pageView.invalidate() bitmap?.recycle() bitmap = null } @@ -141,7 +134,7 @@ abstract class PageDelegate(protected val pageView: PageView) : fun setViewSize(width: Int, height: Int) { viewWidth = width viewHeight = height - invalidate() + pageView.invalidate() centerRectF.set( width * 0.33f, height * 0.33f, width * 0.66f, height * 0.66f @@ -152,7 +145,6 @@ abstract class PageDelegate(protected val pageView: PageView) : if (scroller.computeScrollOffset()) { setTouchPoint(scroller.currX.toFloat(), scroller.currY.toFloat()) } else if (isStarted) { - setTouchPoint(scroller.finalX.toFloat(), scroller.finalY.toFloat(), false) onAnimStop() stopScroll() } @@ -192,14 +184,13 @@ abstract class PageDelegate(protected val pageView: PageView) : onAnimStart() } - abstract fun onAnimStart()//scroller start + open fun onAnimStart() {}//scroller start - abstract fun onDraw(canvas: Canvas)//绘制 + open fun onDraw(canvas: Canvas) {}//绘制 - abstract fun onAnimStop()//scroller finish + open fun onAnimStop() {}//scroller finish - open fun onScroll() {//移动contentView, slidePage - } + open fun onScroll() {}//移动contentView, slidePage @CallSuper open fun setDirection(direction: Direction) { @@ -218,18 +209,17 @@ abstract class PageDelegate(protected val pageView: PageView) : * 触摸事件处理 */ @CallSuper - open fun onTouch(event: MotionEvent): Boolean { - if (isStarted) return false + open fun onTouch(event: MotionEvent) { + if (isStarted) return if (!detector.onTouchEvent(event)) { //GestureDetector.onFling小幅移动不会触发,所以要自己判断 if (event.action == MotionEvent.ACTION_UP && isMoved) { - if (isTextSelected) { - isTextSelected = false + if (selectedOnDown) { + selectedOnDown = false } if (!noNext) onAnimStart() } } - return true } /** @@ -238,6 +228,8 @@ abstract class PageDelegate(protected val pageView: PageView) : override fun onDown(e: MotionEvent): Boolean { if (isTextSelected) { curPage.cancelSelect() + isTextSelected = false + selectedOnDown = true } //是否移动 isMoved = false @@ -258,8 +250,8 @@ abstract class PageDelegate(protected val pageView: PageView) : * 单击 */ override fun onSingleTapUp(e: MotionEvent): Boolean { - if (isTextSelected) { - isTextSelected = false + if (selectedOnDown) { + selectedOnDown = false return true } val x = e.x @@ -272,15 +264,11 @@ abstract class PageDelegate(protected val pageView: PageView) : AppConfig.clickAllNext ) { //设置动画方向 - if (!hasNext()) { - return true - } + if (!hasNext()) return true setDirection(Direction.NEXT) setBitmap() } else { - if (!hasPrev()) { - return true - } + if (!hasPrev()) return true setDirection(Direction.PREV) setBitmap() } @@ -294,7 +282,25 @@ abstract class PageDelegate(protected val pageView: PageView) : * 长按选择 */ override fun onLongPress(e: MotionEvent) { - isTextSelected = curPage.selectText(e) + curPage.selectText(e) { lineIndex, charIndex -> + isTextSelected = true + firstLineIndex = lineIndex + firstCharIndex = charIndex + } + } + + protected fun selectText(event: MotionEvent) { + curPage.selectText(event) { lineIndex, charIndex -> + if (lineIndex > firstLineIndex + || (lineIndex == firstLineIndex && charIndex > firstCharIndex) + ) { + curPage.selectStartMoveIndex(firstLineIndex, firstCharIndex) + curPage.selectEndMoveIndex(lineIndex, charIndex) + } else { + curPage.selectEndMoveIndex(firstLineIndex, firstCharIndex) + curPage.selectStartMoveIndex(lineIndex, charIndex) + } + } } /** diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/ScrollPageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/ScrollPageDelegate.kt index 714c26f89..d90ee8649 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/ScrollPageDelegate.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/ScrollPageDelegate.kt @@ -1,6 +1,5 @@ package io.legado.app.ui.book.read.page.delegate -import android.graphics.Canvas import android.view.MotionEvent import android.view.VelocityTracker import io.legado.app.ui.book.read.page.PageView @@ -21,70 +20,38 @@ class ScrollPageDelegate(pageView: PageView) : PageDelegate(pageView) { ) } - override fun onDraw(canvas: Canvas) { - curPage.onScroll(lastY - touchY) + override fun onScroll() { + curPage.onScroll(touchY - lastY) } - override fun onAnimStop() { - if (!isCancel) { - pageView.fillPage(mDirection) + override fun onTouch(event: MotionEvent) { + when (event.action) { + MotionEvent.ACTION_DOWN -> { + setStartPoint(event.x, event.y) + abort() + mVelocity.clear() + } + MotionEvent.ACTION_MOVE -> { + if (isTextSelected) { + selectText(event) + } else { + onScroll(event) + } + } } + super.onTouch(event) } - override fun onDown(e: MotionEvent): Boolean { - abort() - mVelocity.clear() - mVelocity.addMovement(e) - return super.onDown(e) - } - - override fun onScroll( - e1: MotionEvent, - e2: MotionEvent, - distanceX: Float, - distanceY: Float - ): Boolean { - mVelocity.addMovement(e2) + private fun onScroll(event: MotionEvent) { + mVelocity.addMovement(event) mVelocity.computeCurrentVelocity(velocityDuration) - - if (!isMoved && abs(distanceX) < abs(distanceY)) { - if (distanceY < 0) { - if (atTop) { - //如果上一页不存在 - if (!hasPrev()) { - noNext = true - return true - } - setDirection(Direction.PREV) - } - } else { - if (atBottom) { - //如果不存在表示没有下一页了 - if (!hasNext()) { - noNext = true - return true - } - setDirection(Direction.NEXT) - } - } - isMoved = true + setTouchPoint(event.x, event.y) + if (!isMoved) { + isMoved = abs(startX - event.x) > slop || abs(startY - event.y) > slop } if (isMoved) { isRunning = true - //设置触摸点 - setTouchPoint(e2.x, e2.y) } - return isMoved - } - - override fun onFling( - e1: MotionEvent?, - e2: MotionEvent?, - velocityX: Float, - velocityY: Float - ): Boolean { - mVelocity.addMovement(e2) - return super.onFling(e1, e2, velocityX, velocityY) } override fun onDestroy() { diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextChar.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextChar.kt index 9883e6dab..6fed2fe97 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextChar.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextChar.kt @@ -3,6 +3,6 @@ package io.legado.app.ui.book.read.page.entities data class TextChar( val charData: String, var selected: Boolean = false, - val leftBottomPosition: TextPoint, - val rightTopPosition: TextPoint + val start: Float, + val end: Float ) \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt index 00ae4bff6..26fb31e90 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt @@ -4,6 +4,7 @@ data class TextLine( var text: String = "", val textChars: ArrayList = arrayListOf(), var lineTop: Float = 0f, + var lineBase: Float = 0f, var lineBottom: Float = 0f, val isTitle: Boolean = false, var isReadAloud: Boolean = false diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt index 92d91b1e5..4e6089ddd 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt @@ -1,7 +1,10 @@ package io.legado.app.ui.book.read.page.entities +import android.text.Layout +import android.text.StaticLayout import io.legado.app.App import io.legado.app.R +import io.legado.app.ui.book.read.page.ChapterProvider data class TextPage( var index: Int = 0, @@ -14,6 +17,40 @@ data class TextPage( var height: Int = 0 ) { + @Suppress("DEPRECATION") + fun format(): TextPage { + if (textLines.isEmpty() && ChapterProvider.visibleWidth > 0) { + val layout = StaticLayout( + text, ChapterProvider.contentPaint, ChapterProvider.visibleWidth, + Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false + ) + var y = (ChapterProvider.visibleHeight - layout.height) / 2f + if (y < 0) y = 0f + for (lineIndex in 0 until layout.lineCount) { + val textLine = TextLine() + textLine.lineTop = (ChapterProvider.paddingTop + y - + (layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex))) + textLine.lineBase = (ChapterProvider.paddingTop + y - + (layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))) + textLine.lineBottom = + textLine.lineBase + ChapterProvider.contentPaint.fontMetrics.descent + var x = (ChapterProvider.visibleWidth - layout.getLineMax(lineIndex)) / 2 + textLine.text = + text.substring(layout.getLineStart(lineIndex), layout.getLineEnd(lineIndex)) + for (i in textLine.text.indices) { + val char = textLine.text[i].toString() + val cw = StaticLayout.getDesiredWidth(char, ChapterProvider.contentPaint) + val x1 = x + cw + textLine.textChars.add(TextChar(charData = char, start = x, end = x1)) + x = x1 + } + textLines.add(textLine) + } + height = ChapterProvider.visibleHeight + } + return this + } + fun removePageAloudSpan(): TextPage { textLines.forEach { textLine -> textLine.isReadAloud = false diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPoint.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPoint.kt deleted file mode 100644 index 07bb142b6..000000000 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPoint.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.legado.app.ui.book.read.page.entities - -data class TextPoint( - val x: Float, - val y: Float -) \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 5b375b4cf..c94b59d7c 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -30,6 +30,7 @@ import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.filechooser.FileChooserDialog import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.widget.SelectActionBar +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.utils.* import kotlinx.android.synthetic.main.activity_book_source.* @@ -109,7 +110,7 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity private fun initRecyclerView() { ATH.applyEdgeEffectColor(recycler_view) recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) adapter = BookSourceAdapter(this, this) recycler_view.adapter = adapter val itemTouchCallback = ItemTouchCallback() diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt index 314b45d08..d4a466948 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt @@ -22,7 +22,11 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.customView import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.yesButton -import io.legado.app.utils.* +import io.legado.app.ui.widget.recycler.VerticalDivider +import io.legado.app.utils.applyTint +import io.legado.app.utils.getViewModelOfActivity +import io.legado.app.utils.requestInputMethod +import io.legado.app.utils.splitNotBlank import kotlinx.android.synthetic.main.dialog_edit_text.view.* import kotlinx.android.synthetic.main.dialog_recycler_view.* import kotlinx.android.synthetic.main.item_group_manage.view.* @@ -60,7 +64,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { tool_bar.setOnMenuItemClickListener(this) adapter = GroupAdapter(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter App.db.bookSourceDao().liveGroup().observe(viewLifecycleOwner, Observer { val groups = linkedSetOf() diff --git a/app/src/main/java/io/legado/app/ui/changesource/ChangeSourceDialog.kt b/app/src/main/java/io/legado/app/ui/changesource/ChangeSourceDialog.kt index 4b129acea..d1ce27f2e 100644 --- a/app/src/main/java/io/legado/app/ui/changesource/ChangeSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/changesource/ChangeSourceDialog.kt @@ -18,8 +18,8 @@ import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchBook +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.getPrefBoolean -import io.legado.app.utils.getVerticalDivider import io.legado.app.utils.getViewModel import io.legado.app.utils.putPrefBoolean import kotlinx.android.synthetic.main.dialog_change_source.* @@ -92,7 +92,7 @@ class ChangeSourceDialog : DialogFragment(), private fun initRecyclerView() { adapter = ChangeSourceAdapter(requireContext(), this) recycler_view.layoutManager = LinearLayoutManager(context) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { diff --git a/app/src/main/java/io/legado/app/ui/chapterlist/BookmarkFragment.kt b/app/src/main/java/io/legado/app/ui/chapterlist/BookmarkFragment.kt index c32c8bc42..b2337d0d9 100644 --- a/app/src/main/java/io/legado/app/ui/chapterlist/BookmarkFragment.kt +++ b/app/src/main/java/io/legado/app/ui/chapterlist/BookmarkFragment.kt @@ -14,7 +14,7 @@ import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.data.entities.Bookmark import io.legado.app.lib.theme.ATH -import io.legado.app.utils.getVerticalDivider +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.getViewModelOfActivity import kotlinx.android.synthetic.main.fragment_bookmark.* @@ -38,7 +38,7 @@ class BookmarkFragment : VMBaseFragment(R.layout.fragment_ ATH.applyEdgeEffectColor(recycler_view) adapter = BookmarkAdapter(this) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter } diff --git a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt index 0d9234e36..0bfc9a765 100644 --- a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt +++ b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt @@ -15,7 +15,7 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp import io.legado.app.lib.theme.backgroundColor import io.legado.app.ui.widget.recycler.UpLinearLayoutManager -import io.legado.app.utils.getVerticalDivider +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.getViewModelOfActivity import io.legado.app.utils.observeEvent import kotlinx.android.synthetic.main.fragment_chapter_list.* @@ -48,7 +48,7 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme adapter = ChapterListAdapter(requireContext(), this) mLayoutManager = UpLinearLayoutManager(requireContext()) recycler_view.layoutManager = mLayoutManager - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter } diff --git a/app/src/main/java/io/legado/app/ui/explore/ExploreShowActivity.kt b/app/src/main/java/io/legado/app/ui/explore/ExploreShowActivity.kt index 8cc5d7c7e..08a96a340 100644 --- a/app/src/main/java/io/legado/app/ui/explore/ExploreShowActivity.kt +++ b/app/src/main/java/io/legado/app/ui/explore/ExploreShowActivity.kt @@ -10,7 +10,7 @@ import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchBook import io.legado.app.ui.book.info.BookInfoActivity import io.legado.app.ui.widget.recycler.LoadMoreView -import io.legado.app.utils.getVerticalDivider +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.getViewModel import kotlinx.android.synthetic.main.activity_explore_show.* import org.jetbrains.anko.startActivity @@ -34,7 +34,7 @@ class ExploreShowActivity : VMBaseActivity(R.layout.activi private fun initRecyclerView() { adapter = ExploreShowAdapter(this, this) recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) recycler_view.adapter = adapter loadMoreView = LoadMoreView(this) adapter.addFooterView(loadMoreView) diff --git a/app/src/main/java/io/legado/app/ui/filechooser/FileChooserDialog.kt b/app/src/main/java/io/legado/app/ui/filechooser/FileChooserDialog.kt index 46c1271fc..af8cf50f4 100644 --- a/app/src/main/java/io/legado/app/ui/filechooser/FileChooserDialog.kt +++ b/app/src/main/java/io/legado/app/ui/filechooser/FileChooserDialog.kt @@ -15,7 +15,11 @@ import io.legado.app.R import io.legado.app.constant.Theme import io.legado.app.ui.filechooser.adapter.FileAdapter import io.legado.app.ui.filechooser.adapter.PathAdapter -import io.legado.app.utils.* +import io.legado.app.ui.widget.recycler.VerticalDivider +import io.legado.app.utils.FileUtils +import io.legado.app.utils.applyTint +import io.legado.app.utils.gone +import io.legado.app.utils.visible import kotlinx.android.synthetic.main.dialog_file_chooser.* @@ -133,7 +137,7 @@ class FileChooserDialog : DialogFragment(), fileAdapter = FileAdapter(requireContext(), this) pathAdapter = PathAdapter(requireContext(), this) - rv_file.addItemDecoration(rv_file.getVerticalDivider()) + rv_file.addItemDecoration(VerticalDivider(requireContext())) rv_file.layoutManager = LinearLayoutManager(activity) rv_file.adapter = fileAdapter diff --git a/app/src/main/java/io/legado/app/ui/replacerule/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/replacerule/GroupManageDialog.kt index 6f9a61f4c..df39b9a1d 100644 --- a/app/src/main/java/io/legado/app/ui/replacerule/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/replacerule/GroupManageDialog.kt @@ -22,7 +22,11 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.customView import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.yesButton -import io.legado.app.utils.* +import io.legado.app.ui.widget.recycler.VerticalDivider +import io.legado.app.utils.applyTint +import io.legado.app.utils.getViewModelOfActivity +import io.legado.app.utils.requestInputMethod +import io.legado.app.utils.splitNotBlank import kotlinx.android.synthetic.main.dialog_edit_text.view.* import kotlinx.android.synthetic.main.dialog_recycler_view.* import kotlinx.android.synthetic.main.item_group_manage.view.* @@ -60,7 +64,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { tool_bar.setOnMenuItemClickListener(this) adapter = GroupAdapter(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter App.db.replaceRuleDao().liveGroup().observe(viewLifecycleOwner, Observer { val groups = linkedSetOf() diff --git a/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt b/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt index 9474ad4d1..331c87a5d 100644 --- a/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt +++ b/app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt @@ -28,6 +28,7 @@ import io.legado.app.lib.theme.primaryTextColor import io.legado.app.ui.filechooser.FileChooserDialog import io.legado.app.ui.replacerule.edit.ReplaceEditDialog import io.legado.app.ui.widget.SelectActionBar +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.utils.* import kotlinx.android.synthetic.main.activity_replace_rule.* @@ -77,7 +78,7 @@ class ReplaceRuleActivity : VMBaseActivity(R.layout.activi recycler_view.layoutManager = LinearLayoutManager(this) adapter = ReplaceRuleAdapter(this, this) recycler_view.adapter = adapter - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) val itemTouchCallback = ItemTouchCallback() itemTouchCallback.onItemTouchCallbackListener = adapter itemTouchCallback.isCanDrag = true diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt index 5476657a4..3b53a6475 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt @@ -15,7 +15,7 @@ import io.legado.app.lib.theme.ATH import io.legado.app.ui.rss.read.ReadRssActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.widget.recycler.LoadMoreView -import io.legado.app.utils.getVerticalDivider +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.getViewModel import kotlinx.android.synthetic.main.activity_rss_artivles.* import kotlinx.android.synthetic.main.view_load_more.view.* @@ -70,7 +70,7 @@ class RssArticlesActivity : VMBaseActivity(R.layout.activi private fun initView() { ATH.applyEdgeEffectColor(recycler_view) recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) adapter = RssArticlesAdapter(this, this) recycler_view.adapter = adapter loadMoreView = LoadMoreView(this) diff --git a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt index a8eb39cea..f50329296 100644 --- a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt @@ -10,7 +10,7 @@ import io.legado.app.base.BaseActivity import io.legado.app.data.entities.RssStar import io.legado.app.lib.theme.ATH import io.legado.app.ui.rss.read.ReadRssActivity -import io.legado.app.utils.getVerticalDivider +import io.legado.app.ui.widget.recycler.VerticalDivider import kotlinx.android.synthetic.main.view_refresh_recycler.* import org.jetbrains.anko.startActivity @@ -29,7 +29,7 @@ class RssFavoritesActivity : BaseActivity(R.layout.activity_rss_favorites), private fun initView() { ATH.applyEdgeEffectColor(recycler_view) recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) adapter = RssFavoritesAdapter(this, this) recycler_view.adapter = adapter } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt index 1ba2a567b..391281a4e 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt @@ -22,7 +22,11 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.customView import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.yesButton -import io.legado.app.utils.* +import io.legado.app.ui.widget.recycler.VerticalDivider +import io.legado.app.utils.applyTint +import io.legado.app.utils.getViewModelOfActivity +import io.legado.app.utils.requestInputMethod +import io.legado.app.utils.splitNotBlank import kotlinx.android.synthetic.main.dialog_edit_text.view.* import kotlinx.android.synthetic.main.dialog_recycler_view.* import kotlinx.android.synthetic.main.item_group_manage.view.* @@ -60,7 +64,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { tool_bar.setOnMenuItemClickListener(this) adapter = GroupAdapter(requireContext()) recycler_view.layoutManager = LinearLayoutManager(requireContext()) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter App.db.rssSourceDao().liveGroup().observe(viewLifecycleOwner, Observer { val groups = linkedSetOf() diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt index e83a15c19..0af2de45b 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt @@ -29,6 +29,7 @@ import io.legado.app.ui.filechooser.FileChooserDialog import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.widget.SelectActionBar +import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.utils.* import kotlinx.android.synthetic.main.activity_rss_source.* @@ -104,7 +105,7 @@ class RssSourceActivity : VMBaseActivity(R.layout.activity_r private fun initRecyclerView() { ATH.applyEdgeEffectColor(recycler_view) recycler_view.layoutManager = LinearLayoutManager(this) - recycler_view.addItemDecoration(recycler_view.getVerticalDivider()) + recycler_view.addItemDecoration(VerticalDivider(this)) adapter = RssSourceAdapter(this, this) recycler_view.adapter = adapter val itemTouchCallback = ItemTouchCallback() diff --git a/app/src/main/java/io/legado/app/ui/widget/LabelsBar.kt b/app/src/main/java/io/legado/app/ui/widget/LabelsBar.kt index ab933edbb..2d830ca55 100644 --- a/app/src/main/java/io/legado/app/ui/widget/LabelsBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/LabelsBar.kt @@ -12,6 +12,7 @@ class LabelsBar(context: Context, attrs: AttributeSet?) : LinearLayout(context, private val unUsedViews = arrayListOf() private val usedViews = arrayListOf() + var textSize = 12f fun setLabels(labels: Array) { clear() @@ -51,6 +52,7 @@ class LabelsBar(context: Context, attrs: AttributeSet?) : LinearLayout(context, unUsedViews.removeAt(unUsedViews.lastIndex) } } + tv.textSize = textSize tv.text = label addView(tv) } diff --git a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt index ab931f3ab..d19c8929f 100644 --- a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt @@ -12,8 +12,8 @@ import com.google.android.material.appbar.AppBarLayout import io.legado.app.R import io.legado.app.lib.theme.primaryColor import io.legado.app.utils.activity -import io.legado.app.utils.getNavigationBarHeight -import io.legado.app.utils.getStatusBarHeight +import io.legado.app.utils.navigationBarHeight +import io.legado.app.utils.statusBarHeight import org.jetbrains.anko.backgroundColor import org.jetbrains.anko.bottomPadding import org.jetbrains.anko.topPadding @@ -132,11 +132,11 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a } if (a.getBoolean(R.styleable.TitleBar_fitStatusBar, true)) { - topPadding = context.getStatusBarHeight() + topPadding = context.statusBarHeight } if (a.getBoolean(R.styleable.TitleBar_fitNavigationBar, false)) { - bottomPadding = context.getNavigationBarHeight() + bottomPadding = context.navigationBarHeight } backgroundColor = context.primaryColor diff --git a/app/src/main/java/io/legado/app/ui/widget/recycler/DividerNoLast.kt b/app/src/main/java/io/legado/app/ui/widget/recycler/DividerNoLast.kt new file mode 100644 index 000000000..5c9e38e4d --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/recycler/DividerNoLast.kt @@ -0,0 +1,169 @@ +package io.legado.app.ui.widget.recycler + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.util.Log +import android.view.View +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import kotlin.math.roundToInt + + +/** + * 不画最后一条分隔线 + */ +class DividerNoLast(context: Context, orientation: Int) : + RecyclerView.ItemDecoration() { + + companion object { + const val HORIZONTAL = LinearLayout.HORIZONTAL + const val VERTICAL = LinearLayout.VERTICAL + } + + private val tag = "DividerItem" + private val attrs = intArrayOf(android.R.attr.listDivider) + + private var mDivider: Drawable? = null + + /** + * Current orientation. Either [.HORIZONTAL] or [.VERTICAL]. + */ + private var mOrientation = 0 + + private val mBounds = Rect() + + init { + val a = context.obtainStyledAttributes(attrs) + mDivider = a.getDrawable(0) + if (mDivider == null) { + Log.w( + tag, "@android:attr/listDivider was not set in the theme used for this " + + "DividerItemDecoration. Please set that attribute all call setDrawable()" + ) + } + a.recycle() + setOrientation(orientation) + } + + /** + * Sets the orientation for this divider. This should be called if + * [RecyclerView.LayoutManager] changes orientation. + * + * @param orientation [.HORIZONTAL] or [.VERTICAL] + */ + fun setOrientation(orientation: Int) { + require(!(orientation != HORIZONTAL && orientation != VERTICAL)) { "Invalid orientation. It should be either HORIZONTAL or VERTICAL" } + mOrientation = orientation + } + + /** + * Sets the [Drawable] for this divider. + * + * @param drawable Drawable that should be used as a divider. + */ + fun setDrawable(drawable: Drawable) { + requireNotNull(drawable) { "Drawable cannot be null." } + mDivider = drawable + } + + /** + * @return the [Drawable] for this divider. + */ + fun getDrawable(): Drawable? { + return mDivider + } + + override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { + if (parent.layoutManager == null || mDivider == null) { + return + } + if (mOrientation == VERTICAL) { + drawVertical(c, parent) + } else { + drawHorizontal(c, parent) + } + } + + private fun drawVertical( + canvas: Canvas, + parent: RecyclerView + ) { + canvas.save() + val left: Int + val right: Int + if (parent.clipToPadding) { + left = parent.paddingLeft + right = parent.width - parent.paddingRight + canvas.clipRect( + left, parent.paddingTop, right, + parent.height - parent.paddingBottom + ) + } else { + left = 0 + right = parent.width + } + val childCount = parent.childCount + for (i in 0 until childCount - 1) { + val child = parent.getChildAt(i) + parent.getDecoratedBoundsWithMargins(child, mBounds) + val bottom = mBounds.bottom + child.translationY.roundToInt() + val top = bottom - mDivider!!.intrinsicHeight + mDivider!!.setBounds(left, top, right, bottom) + mDivider!!.draw(canvas) + } + canvas.restore() + } + + private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) { + canvas.save() + val top: Int + val bottom: Int + if (parent.clipToPadding) { + top = parent.paddingTop + bottom = parent.height - parent.paddingBottom + canvas.clipRect( + parent.paddingLeft, top, + parent.width - parent.paddingRight, bottom + ) + } else { + top = 0 + bottom = parent.height + } + val childCount = parent.childCount + for (i in 0 until childCount - 1) { + val child = parent.getChildAt(i) + parent.layoutManager!!.getDecoratedBoundsWithMargins(child, mBounds) + val right = mBounds.right + child.translationX.roundToInt() + val left = right - mDivider!!.intrinsicWidth + mDivider!!.setBounds(left, top, right, bottom) + mDivider!!.draw(canvas) + } + canvas.restore() + } + + override fun getItemOffsets( + outRect: Rect, view: View, parent: RecyclerView, + state: RecyclerView.State + ) { + if (mDivider == null) { + outRect[0, 0, 0] = 0 + return + } + + if (mOrientation == VERTICAL) { + outRect[0, 0, 0] = mDivider!!.intrinsicHeight + } else { + val childAdapterPosition = parent.getChildAdapterPosition(view) + val lastCount = parent.adapter!!.itemCount - 1 + //如果不是最后一条 正常赋值 如果是最后一条 赋值为0 + if (childAdapterPosition != lastCount) { + outRect[0, 0, mDivider!!.intrinsicWidth] = 0 + } else { + outRect[0, 0, 0] = 0 + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt b/app/src/main/java/io/legado/app/ui/widget/recycler/VerticalDivider.kt similarity index 52% rename from app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt rename to app/src/main/java/io/legado/app/ui/widget/recycler/VerticalDivider.kt index 7dbed87ce..2ea450d4c 100644 --- a/app/src/main/java/io/legado/app/utils/RecyclerViewExtensions.kt +++ b/app/src/main/java/io/legado/app/ui/widget/recycler/VerticalDivider.kt @@ -1,15 +1,16 @@ -package io.legado.app.utils +package io.legado.app.ui.widget.recycler +import android.content.Context import androidx.core.content.ContextCompat import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.RecyclerView import io.legado.app.R +class VerticalDivider(context: Context) : DividerItemDecoration(context, VERTICAL) { -fun RecyclerView.getVerticalDivider(): DividerItemDecoration { - return DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply { + init { ContextCompat.getDrawable(context, R.drawable.ic_divider)?.let { this.setDrawable(it) } } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/ContextExtensions.kt b/app/src/main/java/io/legado/app/utils/ContextExtensions.kt index 5b266a343..90415484a 100644 --- a/app/src/main/java/io/legado/app/utils/ContextExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ContextExtensions.kt @@ -1,3 +1,4 @@ +@file:Suppress("unused") package io.legado.app.utils import android.annotation.SuppressLint @@ -30,7 +31,6 @@ fun Context.getPrefBoolean(key: String, defValue: Boolean = false) = fun Context.putPrefBoolean(key: String, value: Boolean = false) = defaultSharedPreferences.edit { putBoolean(key, value) } - fun Context.getPrefInt(key: String, defValue: Int = 0) = defaultSharedPreferences.getInt(key, defValue) @@ -69,24 +69,27 @@ fun Context.getCompatColorStateList(@ColorRes id: Int): ColorStateList? = /** * 系统息屏时间 */ -fun Context.getScreenOffTime(): Int { - var screenOffTime = 0 - try { - screenOffTime = Settings.System.getInt(contentResolver, Settings.System.SCREEN_OFF_TIMEOUT) - } catch (e: Exception) { - e.printStackTrace() - } - return screenOffTime +val Context.sysScreenOffTime: Int + get() { + var screenOffTime = 0 + try { + screenOffTime = Settings.System.getInt(contentResolver, Settings.System.SCREEN_OFF_TIMEOUT) + } catch (e: Exception) { + e.printStackTrace() + } + return screenOffTime } -fun Context.getStatusBarHeight(): Int { - val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") - return resources.getDimensionPixelSize(resourceId) +val Context.statusBarHeight: Int + get() { + val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") + return resources.getDimensionPixelSize(resourceId) } -fun Context.getNavigationBarHeight(): Int { - val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") - return resources.getDimensionPixelSize(resourceId) +val Context.navigationBarHeight: Int + get() { + val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") + return resources.getDimensionPixelSize(resourceId) } fun Context.shareText(title: String, text: String) { @@ -149,10 +152,11 @@ fun Context.sysIsDarkMode(): Boolean { /** * 获取电量 */ -fun Context.getBettery(): Int { - val iFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) - val batteryStatus = registerReceiver(null, iFilter) - return batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1 +val Context.sysBattery: Int + get() { + val iFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) + val batteryStatus = registerReceiver(null, iFilter) + return batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1 } fun Context.openUrl(url: String) { diff --git a/app/src/main/res/drawable/recyclerview_divider_horizontal.xml b/app/src/main/res/drawable/recyclerview_divider_horizontal.xml index d6b50f883..2d2d95362 100644 --- a/app/src/main/res/drawable/recyclerview_divider_horizontal.xml +++ b/app/src/main/res/drawable/recyclerview_divider_horizontal.xml @@ -1,7 +1,7 @@ - + diff --git a/app/src/main/res/layout/dialog_read_aloud.xml b/app/src/main/res/layout/dialog_read_aloud.xml index 282f9cdfe..ea04696d4 100644 --- a/app/src/main/res/layout/dialog_read_aloud.xml +++ b/app/src/main/res/layout/dialog_read_aloud.xml @@ -154,8 +154,8 @@ android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:background="?android:attr/selectableItemBackgroundBorderless" - android:tooltipText="@string/other_setting" - android:contentDescription="@string/other_setting" + android:tooltipText="@string/other_aloud_setting" + android:contentDescription="@string/other_aloud_setting" android:src="@drawable/ic_settings" android:tint="@color/tv_text_default" tools:ignore="UnusedAttribute" /> diff --git a/app/src/main/res/layout/dialog_read_padding.xml b/app/src/main/res/layout/dialog_read_padding.xml index 648f062a3..37e3b8cc4 100644 --- a/app/src/main/res/layout/dialog_read_padding.xml +++ b/app/src/main/res/layout/dialog_read_padding.xml @@ -8,6 +8,7 @@ android:orientation="vertical"> 更多菜单 + 其它朗读设置