重新规划了阅读设置与相关修复 #251
This commit is contained in:
@@ -32,6 +32,7 @@ import io.legado.app.model.CacheBook
|
||||
import io.legado.app.model.ReadBook
|
||||
import io.legado.app.ui.book.read.config.BgTextConfigDialog
|
||||
import io.legado.app.ui.book.read.config.ClickActionConfigDialog
|
||||
import io.legado.app.ui.book.read.config.InfoConfigDialog
|
||||
import io.legado.app.ui.book.read.config.PaddingConfigDialog
|
||||
import io.legado.app.ui.book.read.config.PageKeyDialog
|
||||
import io.legado.app.ui.file.HandleFileContract
|
||||
@@ -127,7 +128,7 @@ abstract class BaseReadBookActivity :
|
||||
}
|
||||
|
||||
fun showPaddingConfig() {
|
||||
showDialogFragment<PaddingConfigDialog>()
|
||||
showDialogFragment<InfoConfigDialog>()
|
||||
}
|
||||
|
||||
fun showBgTextConfig() {
|
||||
|
||||
@@ -1748,7 +1748,10 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
when (value) {
|
||||
0 -> upSystemUiVisibility()
|
||||
1 -> readView.upBg()
|
||||
2 -> readView.upStyle()
|
||||
2 -> {
|
||||
readView.upStyle()
|
||||
binding.readMenu.reset()
|
||||
}
|
||||
3 -> readView.upBgAlpha()
|
||||
4 -> readView.upPageSlopSquare()
|
||||
5 -> if (isInitFinish) ReadBook.loadContent(resetPageOffset = false)
|
||||
|
||||
@@ -115,7 +115,6 @@ class BgTextConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_bg
|
||||
ItemBgImageBinding.inflate(layoutInflater, it, false).apply {
|
||||
tvName.text = getString(R.string.select_image)
|
||||
ivBg.setImageResource(R.drawable.ic_add)
|
||||
swUnderline.isGone = ReadBook.book?.isImage == true
|
||||
root.setOnClickListener {
|
||||
selectBgImage.launch()
|
||||
}
|
||||
@@ -130,9 +129,6 @@ class BgTextConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_bg
|
||||
private fun initData() = with(ReadBookConfig.durConfig) {
|
||||
binding.tvName.text = name.ifBlank { "文字" }
|
||||
binding.swDarkStatusIcon.isChecked = curStatusIconDark()
|
||||
binding.swUnderline.isChecked = underline
|
||||
binding.swDottedline.isChecked = dottedLine
|
||||
binding.swDottedline.isEnabled = underline
|
||||
binding.sbBgAlpha.value = ReadBookConfig.bgAlpha.toFloat()
|
||||
binding.dottedRatio.valueFormat = {
|
||||
(ReadBookConfig.dottedRatio * 100).toInt().toString()
|
||||
@@ -175,27 +171,6 @@ class BgTextConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_bg
|
||||
setCurStatusIconDark(isChecked)
|
||||
(activity as? ReadBookActivity)?.upSystemUiVisibility()
|
||||
}
|
||||
binding.swUnderline.setOnCheckedChangeListener { _, isChecked ->
|
||||
underline = isChecked
|
||||
binding.swDottedline.isEnabled = isChecked
|
||||
if (!isChecked) {
|
||||
dottedLine = false
|
||||
binding.swDottedline.isChecked = false
|
||||
}
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(6, 9, 11))
|
||||
}
|
||||
binding.swDottedline.setOnCheckedChangeListener { _, isChecked ->
|
||||
dottedLine = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(6, 9, 11))
|
||||
}
|
||||
binding.tvTextColor.setOnClickListener {
|
||||
ColorPickerDialog.newBuilder()
|
||||
.setColor(curTextColor())
|
||||
.setShowAlphaSlider(false)
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setDialogId(TEXT_COLOR)
|
||||
.show(requireActivity())
|
||||
}
|
||||
binding.tvBgColor.setOnClickListener {
|
||||
val bgColor =
|
||||
if (curBgType() == 0) curBgStr().toColorInt()
|
||||
|
||||
@@ -24,10 +24,13 @@ import io.legado.app.constant.PreferKey
|
||||
import io.legado.app.databinding.DialogFontSelectBinding
|
||||
import io.legado.app.databinding.ItemFontBinding
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.ReadBookConfig.dottedLine
|
||||
import io.legado.app.help.config.ReadBookConfig.underline
|
||||
import io.legado.app.lib.dialogs.SelectItem
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.permission.Permissions
|
||||
import io.legado.app.lib.permission.PermissionsCompat
|
||||
import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.TEXT_COLOR
|
||||
import io.legado.app.ui.file.HandleFileContract
|
||||
import io.legado.app.utils.FileDoc
|
||||
import io.legado.app.utils.FileUtils
|
||||
@@ -40,6 +43,7 @@ import io.legado.app.utils.invisible
|
||||
import io.legado.app.utils.isContentScheme
|
||||
import io.legado.app.utils.list
|
||||
import io.legado.app.utils.listFileDocs
|
||||
import io.legado.app.utils.observeEvent
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.printOnDebug
|
||||
import io.legado.app.utils.putPrefString
|
||||
@@ -47,14 +51,14 @@ import io.legado.app.utils.toastOnUi
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import io.legado.app.utils.visible
|
||||
import kotlinx.coroutines.launch
|
||||
import splitties.resources.color
|
||||
import java.io.File
|
||||
import java.net.URLDecoder
|
||||
|
||||
/**
|
||||
* 字体选择对话框
|
||||
*/
|
||||
class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_select),
|
||||
Toolbar.OnMenuItemClickListener {
|
||||
class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_select) {
|
||||
|
||||
companion object {
|
||||
const val S_COLOR = 123
|
||||
@@ -88,14 +92,14 @@ class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_sele
|
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
//binding.toolBar.setBackgroundColor(primaryColor)
|
||||
binding.toolBar.setTitle(R.string.select_font)
|
||||
binding.toolBar.inflateMenu(R.menu.font_select)
|
||||
binding.toolBar.menu.applyTint(requireContext())
|
||||
binding.toolBar.setOnMenuItemClickListener(this)
|
||||
binding.recyclerView.layoutManager = GridLayoutManager(context, 2)
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
|
||||
observeEvent<ArrayList<Int>>(EventBus.UP_CONFIG) { list ->
|
||||
if (list.contains(2)) {
|
||||
binding.btnTextColor.color = ReadBookConfig.durConfig.curTextColor()
|
||||
binding.btnShadowColor.color = ReadBookConfig.durConfig.curTextShadowColor()
|
||||
}
|
||||
}
|
||||
initView()
|
||||
upView()
|
||||
initViewEvent()
|
||||
@@ -118,7 +122,10 @@ class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_sele
|
||||
loadFontFilesByPermission(fontPath)
|
||||
}
|
||||
}
|
||||
|
||||
binding.btnTextColor.color = ReadBookConfig.durConfig.curTextColor()
|
||||
binding.swUnderline.isChecked = underline
|
||||
binding.swDottedline.isChecked = dottedLine
|
||||
binding.swDottedline.isEnabled = underline
|
||||
dsbTextLetterSpacing.valueFormat = {
|
||||
((it - 50) / 100f).toString()
|
||||
}
|
||||
@@ -126,17 +133,19 @@ class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_sele
|
||||
binding.dsbShadowRadius.valueFormat = { "$it px" }
|
||||
binding.dsbShadowDx.valueFormat = { "$it px" }
|
||||
binding.dsbShadowDy.valueFormat = { "$it px" }
|
||||
|
||||
binding.textIndentDropdown.apply {
|
||||
val items = listOf("0", "1", "2", "3", "4")
|
||||
val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, items)
|
||||
setAdapter(adapter)
|
||||
val currentIndex = ReadBookConfig.paragraphIndent.length.coerceIn(0, items.lastIndex)
|
||||
setText(items[currentIndex], false)
|
||||
setOnItemClickListener { _, _, position, _ ->
|
||||
ReadBookConfig.paragraphIndent = " ".repeat(position)
|
||||
binding.dsbParagraphSpacing.valueFormat = { value ->
|
||||
(value / 10f).toString()
|
||||
}
|
||||
binding.btnIndentLayout.apply {
|
||||
valueFormat = { value ->
|
||||
value.toString()
|
||||
}
|
||||
onChanged = { value ->
|
||||
val indentCount = value.coerceIn(0, 4)
|
||||
ReadBookConfig.paragraphIndent = " ".repeat(indentCount)
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
}
|
||||
progress = ReadBookConfig.paragraphIndent.length
|
||||
}
|
||||
|
||||
val weightOptions = context?.resources?.getStringArray(R.array.text_font_weight)
|
||||
@@ -172,6 +181,7 @@ class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_sele
|
||||
|
||||
binding.btnTextItalic.isChecked = ReadBookConfig.textItalic
|
||||
binding.btnTextShadow.isChecked = ReadBookConfig.textShadow
|
||||
binding.btnShadowColor.color = ReadBookConfig.textShadowColor
|
||||
}
|
||||
|
||||
private fun initViewEvent() = binding.run {
|
||||
@@ -183,21 +193,48 @@ class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_sele
|
||||
ReadBookConfig.lineSpacingExtra = it
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
}
|
||||
binding.dsbParagraphSpacing.apply {
|
||||
valueFrom = 0f
|
||||
valueTo = 20f
|
||||
stepSize = 1f
|
||||
value = ReadBookConfig.paragraphSpacing.toFloat()
|
||||
textParagraphSpacing.text = (ReadBookConfig.paragraphSpacing.toFloat() / 10f).toString()
|
||||
addOnChangeListener { slider, newValue, fromUser ->
|
||||
binding.textParagraphSpacing.text = (newValue / 10f).toString()
|
||||
binding.btnTextColor.setOnClickListener {
|
||||
ColorPickerDialog.newBuilder()
|
||||
.setColor(ReadBookConfig.durConfig.curTextColor())
|
||||
.setShowAlphaSlider(false)
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setDialogId(TEXT_COLOR)
|
||||
.show(requireActivity())
|
||||
}
|
||||
|
||||
if (fromUser) {
|
||||
ReadBookConfig.paragraphSpacing = newValue.toInt()
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
binding.swUnderline.addOnCheckedChangeListener { _, isChecked ->
|
||||
underline = isChecked
|
||||
binding.swDottedline.isEnabled = isChecked
|
||||
if (!isChecked) {
|
||||
dottedLine = false
|
||||
binding.swDottedline.isChecked = false
|
||||
}
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(6, 9, 11))
|
||||
}
|
||||
binding.swDottedline.addOnCheckedChangeListener { _, isChecked ->
|
||||
dottedLine = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(6, 9, 11))
|
||||
}
|
||||
binding.btnDefaultFonts.setOnClickListener {
|
||||
val requireContext = requireContext()
|
||||
alert(titleResource = R.string.system_typeface) {
|
||||
items(
|
||||
requireContext.resources.getStringArray(R.array.system_typefaces).toList()
|
||||
) { _, i ->
|
||||
AppConfig.systemTypefaces = i
|
||||
onDefaultFontChange()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.btnOtherDir.setOnClickListener {
|
||||
openFolder()
|
||||
}
|
||||
binding.dsbParagraphSpacing.onChanged = { value ->
|
||||
ReadBookConfig.paragraphSpacing = value
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
}
|
||||
|
||||
binding.btnTextItalic.addOnCheckedChangeListener { _, isChecked ->
|
||||
ReadBookConfig.textItalic = isChecked
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
@@ -233,34 +270,13 @@ class FontSelectDialog : BaseBottomSheetDialogFragment(R.layout.dialog_font_sele
|
||||
ReadBookConfig.let {
|
||||
dsbTextLetterSpacing.progress = (it.letterSpacing * 100).toInt() + 50
|
||||
dsbLineSize.progress = it.lineSpacingExtra
|
||||
dsbParagraphSpacing.value = it.paragraphSpacing.toFloat()
|
||||
dsbParagraphSpacing.progress = it.paragraphSpacing
|
||||
binding.dsbShadowRadius.progress = it.shadowRadius.toInt()
|
||||
binding.dsbShadowDx.progress = it.shadowDx.toInt()
|
||||
binding.dsbShadowDy.progress = it.shadowDy.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
when (item?.itemId) {
|
||||
R.id.menu_default -> {
|
||||
val requireContext = requireContext()
|
||||
alert(titleResource = R.string.system_typeface) {
|
||||
items(
|
||||
requireContext.resources.getStringArray(R.array.system_typefaces).toList()
|
||||
) { _, i ->
|
||||
AppConfig.systemTypefaces = i
|
||||
onDefaultFontChange()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
R.id.menu_other -> {
|
||||
openFolder()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun openFolder() {
|
||||
lifecycleScope.launch {
|
||||
val defaultPath = "SD${File.separator}Fonts"
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
package io.legado.app.ui.book.read.config
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BaseBottomSheetDialogFragment
|
||||
import io.legado.app.constant.EventBus
|
||||
import io.legado.app.databinding.DialogReadInfoBinding
|
||||
import io.legado.app.help.config.ReadBookConfig
|
||||
import io.legado.app.help.config.ReadTipConfig
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.model.ReadBook
|
||||
import io.legado.app.ui.book.read.config.TipConfigDialog.Companion.TIP_COLOR
|
||||
import io.legado.app.ui.book.read.config.TipConfigDialog.Companion.TIP_DIVIDER_COLOR
|
||||
import io.legado.app.ui.book.read.page.provider.ChapterProvider
|
||||
import io.legado.app.utils.getCompatColor
|
||||
import io.legado.app.utils.observeEvent
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
|
||||
class InfoConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_info) {
|
||||
|
||||
private val binding by viewBinding(DialogReadInfoBinding::bind)
|
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
initView()
|
||||
initEvent()
|
||||
observeEvent<String>(EventBus.TIP_COLOR) {
|
||||
upTvTipColor()
|
||||
upTvTipDividerColor()
|
||||
}
|
||||
observeEvent<ArrayList<Int>>(EventBus.UP_CONFIG) { list ->
|
||||
if (list.contains(2)) {
|
||||
upBtnHeaderMode()
|
||||
upBtnFooterMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
ReadTipConfig.run {
|
||||
tipNames.let { tipNames ->
|
||||
binding.tvHeaderLeft.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipHeaderLeft)) { tipNames[none] }
|
||||
binding.tvHeaderMiddle.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipHeaderMiddle)) { tipNames[none] }
|
||||
binding.tvHeaderRight.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipHeaderRight)) { tipNames[none] }
|
||||
binding.tvFooterLeft.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipFooterLeft)) { tipNames[none] }
|
||||
binding.tvFooterMiddle.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipFooterMiddle)) { tipNames[none] }
|
||||
binding.tvFooterRight.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipFooterRight)) { tipNames[none] }
|
||||
}
|
||||
}
|
||||
binding.btnPaddingSetting.setOnClickListener {
|
||||
showDialogFragment<PaddingConfigDialog>()
|
||||
}
|
||||
upTvTipColor()
|
||||
upTvTipDividerColor()
|
||||
}
|
||||
|
||||
private fun upTvTipColor() {
|
||||
val tipColor = if (ReadTipConfig.tipColor == 0) {
|
||||
ReadBookConfig.textColor
|
||||
} else {
|
||||
ReadTipConfig.tipColor
|
||||
}
|
||||
binding.btnTipColor.color = tipColor
|
||||
}
|
||||
|
||||
private fun upTvTipDividerColor() {
|
||||
val tipDividerColor = when (ReadTipConfig.tipDividerColor) {
|
||||
-1 -> getCompatColor(R.color.divider)
|
||||
0 -> ReadBookConfig.textColor
|
||||
else -> ReadTipConfig.tipDividerColor
|
||||
}
|
||||
binding.btnDividerColor.color = tipDividerColor
|
||||
}
|
||||
|
||||
private fun upBtnHeaderMode() {
|
||||
val headerModes = ReadTipConfig.getHeaderModes(requireContext())
|
||||
binding.btnHeaderMode.text = headerModes[ReadTipConfig.headerMode] ?: getString(R.string.header)
|
||||
}
|
||||
|
||||
private fun upBtnFooterMode() {
|
||||
val footerModes = ReadTipConfig.getFooterModes(requireContext())
|
||||
binding.btnFooterMode.text = footerModes[ReadTipConfig.footerMode] ?: getString(R.string.footer)
|
||||
}
|
||||
|
||||
private fun initEvent() = binding.run {
|
||||
|
||||
val headerModes = ReadTipConfig.getHeaderModes(requireContext())
|
||||
binding.btnHeaderMode.text = headerModes[ReadTipConfig.headerMode] ?: getString(R.string.header)
|
||||
binding.btnHeaderMode.setOnClickListener {
|
||||
val items = headerModes.values.toList()
|
||||
context?.selector(items = items) { _, index ->
|
||||
val selectedKey = headerModes.keys.toList()[index]
|
||||
ReadTipConfig.headerMode = selectedKey
|
||||
binding.btnHeaderMode.text = headerModes[selectedKey]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
}
|
||||
|
||||
val footerModes = ReadTipConfig.getFooterModes(requireContext())
|
||||
binding.btnFooterMode.text = footerModes[ReadTipConfig.footerMode] ?: getString(R.string.footer)
|
||||
binding.btnFooterMode.setOnClickListener {
|
||||
val items = footerModes.values.toList()
|
||||
context?.selector(items = items) { _, index ->
|
||||
val selectedKey = footerModes.keys.toList()[index]
|
||||
ReadTipConfig.footerMode = selectedKey
|
||||
binding.btnFooterMode.text = footerModes[selectedKey]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
}
|
||||
|
||||
llHeaderLeft.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipHeaderLeft = tipValue
|
||||
tvHeaderLeft.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llHeaderMiddle.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipHeaderMiddle = tipValue
|
||||
tvHeaderMiddle.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llHeaderRight.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipHeaderRight = tipValue
|
||||
tvHeaderRight.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llFooterLeft.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipFooterLeft = tipValue
|
||||
tvFooterLeft.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llFooterMiddle.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipFooterMiddle = tipValue
|
||||
tvFooterMiddle.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llFooterRight.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipFooterRight = tipValue
|
||||
tvFooterRight.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
btnTipColor.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipColorNames) { _, i ->
|
||||
when (i) {
|
||||
0 -> {
|
||||
ReadTipConfig.tipColor = 0
|
||||
upTvTipColor()
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
|
||||
1 -> ColorPickerDialog.newBuilder()
|
||||
.setShowAlphaSlider(false)
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setDialogId(TIP_COLOR)
|
||||
.show(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
||||
btnDividerColor.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipDividerColorNames) { _, i ->
|
||||
when (i) {
|
||||
0, 1 -> {
|
||||
ReadTipConfig.tipDividerColor = i - 1
|
||||
upTvTipDividerColor()
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
|
||||
2 -> ColorPickerDialog.newBuilder()
|
||||
.setShowAlphaSlider(false)
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setDialogId(TIP_DIVIDER_COLOR)
|
||||
.show(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearRepeat(repeat: Int) = ReadTipConfig.apply {
|
||||
if (repeat != none) {
|
||||
if (tipHeaderLeft == repeat) {
|
||||
tipHeaderLeft = none
|
||||
binding.tvHeaderLeft.text = tipNames[none]
|
||||
}
|
||||
if (tipHeaderMiddle == repeat) {
|
||||
tipHeaderMiddle = none
|
||||
binding.tvHeaderMiddle.text = tipNames[none]
|
||||
}
|
||||
if (tipHeaderRight == repeat) {
|
||||
tipHeaderRight = none
|
||||
binding.tvHeaderRight.text = tipNames[none]
|
||||
}
|
||||
if (tipFooterLeft == repeat) {
|
||||
tipFooterLeft = none
|
||||
binding.tvFooterLeft.text = tipNames[none]
|
||||
}
|
||||
if (tipFooterMiddle == repeat) {
|
||||
tipFooterMiddle = none
|
||||
binding.tvFooterMiddle.text = tipNames[none]
|
||||
}
|
||||
if (tipFooterRight == repeat) {
|
||||
tipFooterRight = none
|
||||
binding.tvFooterRight.text = tipNames[none]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -208,17 +208,14 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
|
||||
tvStyle.text = item.name.ifBlank { "文字" }
|
||||
tvStyle.setTextColor(item.curTextColor())
|
||||
ivStyle.setImageDrawable(item.curBgDrawable(100, 150))
|
||||
cdStyle.strokeWidth = 1.dpToPx()
|
||||
if (ReadBookConfig.styleSelect == holder.layoutPosition) {
|
||||
llStyle.gravity = Gravity.TOP
|
||||
cdStyle.cardElevation = 1f.dpToPx()
|
||||
cdStyle.radius = 16f.dpToPx()
|
||||
cdStyle.strokeWidth = 1.dpToPx()
|
||||
cdStyle.radius = 32f.dpToPx()
|
||||
//cdStyle.strokeColor = item.curTextColor()
|
||||
//tvStyle.setTextBold(true)
|
||||
} else {
|
||||
cdStyle.cardElevation = 2f.dpToPx()
|
||||
cdStyle.radius = 32f.dpToPx()
|
||||
cdStyle.strokeWidth = 0
|
||||
cdStyle.radius = 8f.dpToPx()
|
||||
//cdStyle.strokeColor = item.curTextColor()
|
||||
//tvStyle.setTextBold(false)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import io.legado.app.utils.hexString
|
||||
import io.legado.app.utils.observeEvent
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.requestInputMethod
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
@@ -41,10 +42,6 @@ class TipConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_tip_config
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
initView()
|
||||
initEvent()
|
||||
observeEvent<String>(EventBus.TIP_COLOR) {
|
||||
upTvTipColor()
|
||||
upTvTipDividerColor()
|
||||
}
|
||||
observeEvent<Boolean>(EventBus.UPDATE_READ_ACTION_BAR) {
|
||||
binding.abtnBackgroundColor.color = ReadBookConfig.durConfig.curMenuBg()
|
||||
binding.abtnAccentColor.color = ReadBookConfig.durConfig.curMenuAc()
|
||||
@@ -62,7 +59,6 @@ class TipConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_tip_config
|
||||
val weightOptions = context?.resources?.getStringArray(R.array.text_font_weight)
|
||||
val weightValues = listOf(0, 1, 2)
|
||||
val initialIndex = weightValues.indexOf(ReadBookConfig.titleBold)
|
||||
binding.textFontWeightConverter.text = weightOptions?.getOrNull(initialIndex) ?: "自定义"
|
||||
binding.textFontWeightConverter.setOnClickListener {
|
||||
context?.alert(titleResource = R.string.text_font_weight_converter) {
|
||||
weightOptions?.let { options ->
|
||||
@@ -186,82 +182,6 @@ class TipConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_tip_config
|
||||
binding.dsbTitleSize.progress = ReadBookConfig.titleSize
|
||||
binding.dsbTitleTop.progress = ReadBookConfig.titleTopSpacing
|
||||
binding.dsbTitleBottom.progress = ReadBookConfig.titleBottomSpacing
|
||||
|
||||
val headerModes = ReadTipConfig.getHeaderModes(requireContext())
|
||||
binding.chipHeaderMode.removeAllViews()
|
||||
|
||||
headerModes.forEach { (key, value) ->
|
||||
val chip = Chip(requireContext()).apply {
|
||||
id = View.generateViewId()
|
||||
text = value
|
||||
isCheckable = true
|
||||
isClickable = true
|
||||
tag = key
|
||||
}
|
||||
|
||||
binding.chipHeaderMode.addView(chip)
|
||||
|
||||
if (key == ReadTipConfig.headerMode) {
|
||||
chip.isChecked = true
|
||||
}
|
||||
}
|
||||
|
||||
val footerModes = ReadTipConfig.getFooterModes(requireContext())
|
||||
binding.chipFooterMode.removeAllViews()
|
||||
|
||||
footerModes.forEach { (key, value) ->
|
||||
val chip = Chip(requireContext()).apply {
|
||||
id = View.generateViewId()
|
||||
text = value
|
||||
isCheckable = true
|
||||
isClickable = true
|
||||
tag = key
|
||||
}
|
||||
|
||||
binding.chipFooterMode.addView(chip)
|
||||
|
||||
if (key == ReadTipConfig.footerMode) {
|
||||
chip.isChecked = true
|
||||
}
|
||||
}
|
||||
|
||||
ReadTipConfig.run {
|
||||
tipNames.let { tipNames ->
|
||||
binding.tvHeaderLeft.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipHeaderLeft)) { tipNames[none] }
|
||||
binding.tvHeaderMiddle.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipHeaderMiddle)) { tipNames[none] }
|
||||
binding.tvHeaderRight.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipHeaderRight)) { tipNames[none] }
|
||||
binding.tvFooterLeft.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipFooterLeft)) { tipNames[none] }
|
||||
binding.tvFooterMiddle.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipFooterMiddle)) { tipNames[none] }
|
||||
binding.tvFooterRight.text =
|
||||
tipNames.getOrElse(tipValues.indexOf(tipFooterRight)) { tipNames[none] }
|
||||
}
|
||||
}
|
||||
upTvTipColor()
|
||||
upTvTipDividerColor()
|
||||
}
|
||||
|
||||
private fun upTvTipColor() {
|
||||
val tipColorNames = ReadTipConfig.tipColorNames
|
||||
val tipColor = ReadTipConfig.tipColor
|
||||
binding.tvTipColor.text = if (tipColor == 0) {
|
||||
tipColorNames.first()
|
||||
} else {
|
||||
"#${tipColor.hexString}"
|
||||
}
|
||||
}
|
||||
|
||||
private fun upTvTipDividerColor() {
|
||||
val tipDividerColorNames = ReadTipConfig.tipDividerColorNames
|
||||
val tipDividerColor = ReadTipConfig.tipDividerColor
|
||||
binding.tvTipDividerColor.text = when (tipDividerColor) {
|
||||
-1, 0 -> tipDividerColorNames[tipDividerColor + 1]
|
||||
else -> "#${tipDividerColor.hexString}"
|
||||
}
|
||||
}
|
||||
|
||||
private fun initEvent() = binding.run {
|
||||
@@ -291,139 +211,6 @@ class TipConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_tip_config
|
||||
ReadBookConfig.titleBottomSpacing = it
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
}
|
||||
chipHeaderMode.setOnCheckedStateChangeListener { group, checkedIds ->
|
||||
if (checkedIds.isNotEmpty()) {
|
||||
val selectedChip = group.findViewById<Chip>(checkedIds[0])
|
||||
val mode = selectedChip.tag as Int
|
||||
ReadTipConfig.headerMode = mode
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
}
|
||||
chipFooterMode.setOnCheckedStateChangeListener { group, checkedIds ->
|
||||
if (checkedIds.isNotEmpty()) {
|
||||
val selectedChip = group.findViewById<Chip>(checkedIds[0])
|
||||
val mode = selectedChip.tag as Int
|
||||
ReadTipConfig.footerMode = mode
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
}
|
||||
llHeaderLeft.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipHeaderLeft = tipValue
|
||||
tvHeaderLeft.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llHeaderMiddle.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipHeaderMiddle = tipValue
|
||||
tvHeaderMiddle.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llHeaderRight.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipHeaderRight = tipValue
|
||||
tvHeaderRight.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llFooterLeft.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipFooterLeft = tipValue
|
||||
tvFooterLeft.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llFooterMiddle.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipFooterMiddle = tipValue
|
||||
tvFooterMiddle.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llFooterRight.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipNames) { _, i ->
|
||||
val tipValue = ReadTipConfig.tipValues[i]
|
||||
clearRepeat(tipValue)
|
||||
ReadTipConfig.tipFooterRight = tipValue
|
||||
tvFooterRight.text = ReadTipConfig.tipNames[i]
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2, 6))
|
||||
}
|
||||
}
|
||||
llTipColor.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipColorNames) { _, i ->
|
||||
when (i) {
|
||||
0 -> {
|
||||
ReadTipConfig.tipColor = 0
|
||||
upTvTipColor()
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
|
||||
1 -> ColorPickerDialog.newBuilder()
|
||||
.setShowAlphaSlider(false)
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setDialogId(TIP_COLOR)
|
||||
.show(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
||||
llTipDividerColor.setOnClickListener {
|
||||
context?.selector(items = ReadTipConfig.tipDividerColorNames) { _, i ->
|
||||
when (i) {
|
||||
0, 1 -> {
|
||||
ReadTipConfig.tipDividerColor = i - 1
|
||||
upTvTipDividerColor()
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(2))
|
||||
}
|
||||
|
||||
2 -> ColorPickerDialog.newBuilder()
|
||||
.setShowAlphaSlider(false)
|
||||
.setDialogType(ColorPickerDialog.TYPE_CUSTOM)
|
||||
.setDialogId(TIP_DIVIDER_COLOR)
|
||||
.show(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearRepeat(repeat: Int) = ReadTipConfig.apply {
|
||||
if (repeat != none) {
|
||||
if (tipHeaderLeft == repeat) {
|
||||
tipHeaderLeft = none
|
||||
binding.tvHeaderLeft.text = tipNames[none]
|
||||
}
|
||||
if (tipHeaderMiddle == repeat) {
|
||||
tipHeaderMiddle = none
|
||||
binding.tvHeaderMiddle.text = tipNames[none]
|
||||
}
|
||||
if (tipHeaderRight == repeat) {
|
||||
tipHeaderRight = none
|
||||
binding.tvHeaderRight.text = tipNames[none]
|
||||
}
|
||||
if (tipFooterLeft == repeat) {
|
||||
tipFooterLeft = none
|
||||
binding.tvFooterLeft.text = tipNames[none]
|
||||
}
|
||||
if (tipFooterMiddle == repeat) {
|
||||
tipFooterMiddle = none
|
||||
binding.tvFooterMiddle.text = tipNames[none]
|
||||
}
|
||||
if (tipFooterRight == repeat) {
|
||||
tipFooterRight = none
|
||||
binding.tvFooterRight.text = tipNames[none]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,10 +20,10 @@ class AccentColorButton @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
init {
|
||||
setPaddingRelative(14.dpToPx(), 8.dpToPx(), 6.dpToPx(), 8.dpToPx())
|
||||
setPaddingRelative(14.dpToPx(), 8.dpToPx(), 10.dpToPx(), 8.dpToPx())
|
||||
iconGravity = ICON_GRAVITY_END
|
||||
iconPadding = 8.dpToPx()
|
||||
iconSize = 28.dpToPx()
|
||||
iconSize = 24.dpToPx()
|
||||
}
|
||||
|
||||
private fun createColorPreviewDrawable(color: Int): Drawable {
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
package io.legado.app.ui.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import io.legado.app.R
|
||||
import io.legado.app.databinding.ViewSimpleSliderBinding
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
|
||||
@SuppressLint("ViewConstructor", "ClickableViewAccessibility")
|
||||
class SimpleSliderView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : LinearLayout(context, attrs) {
|
||||
|
||||
private val binding = ViewSimpleSliderBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
private var _orientation: Int = 1
|
||||
private var _progress = 0
|
||||
private var _max = 100
|
||||
private var _min = 0
|
||||
private val isBottomBackground: Boolean
|
||||
|
||||
var valueFormat: ((Int) -> String)? = null
|
||||
var onChanged: ((Int) -> Unit)? = null
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
private val repeatInterval = 320L
|
||||
|
||||
private val tvTit: TextView
|
||||
|
||||
var progress: Int
|
||||
get() = _progress
|
||||
set(value) {
|
||||
_progress = value.coerceIn(_min, _max)
|
||||
updateValue()
|
||||
}
|
||||
|
||||
var max: Int
|
||||
get() = _max
|
||||
set(value) {
|
||||
_max = value
|
||||
_progress = _progress.coerceAtMost(_max)
|
||||
updateValue()
|
||||
}
|
||||
|
||||
var min: Int
|
||||
get() = _min
|
||||
set(value) {
|
||||
_min = value
|
||||
_progress = _progress.coerceAtLeast(_min)
|
||||
updateValue()
|
||||
}
|
||||
|
||||
init {
|
||||
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailSeekBar)
|
||||
isBottomBackground = typedArray.getBoolean(R.styleable.DetailSeekBar_isBottomBackground, false)
|
||||
val title = typedArray.getText(R.styleable.DetailSeekBar_title)
|
||||
_max = typedArray.getInt(R.styleable.DetailSeekBar_max, 100)
|
||||
_min = typedArray.getInt(R.styleable.DetailSeekBar_min, 0)
|
||||
_progress = _progress.coerceIn(_min, _max)
|
||||
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.SimpleCounterView)
|
||||
_orientation = ta.getInt(R.styleable.SimpleCounterView_orientation, 1)
|
||||
ta.recycle()
|
||||
|
||||
val slider = binding.slider
|
||||
slider.valueFrom = _min.toFloat()
|
||||
slider.valueTo = _max.toFloat()
|
||||
slider.value = _progress.toFloat()
|
||||
|
||||
slider.addOnChangeListener { _, value, fromUser ->
|
||||
if (fromUser) {
|
||||
_progress = value.toInt()
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
}
|
||||
}
|
||||
|
||||
tvTit = binding.tvSeekTitleVertical
|
||||
typedArray.recycle()
|
||||
|
||||
tvTit.text = title
|
||||
TooltipCompat.setTooltipText(tvTit, title)
|
||||
|
||||
binding.tvSeekValue.setOnClickListener {
|
||||
showSeekBarDialog()
|
||||
}
|
||||
|
||||
updateValue()
|
||||
}
|
||||
|
||||
private fun showSeekBarDialog() {
|
||||
context.alert(title = null, message = null) {
|
||||
customView {
|
||||
val detailSeekBar = DetailSeekBar(ctx).apply {
|
||||
max = _max
|
||||
min = _min
|
||||
progress = _progress
|
||||
valueFormat = this@SimpleSliderView.valueFormat
|
||||
setTitle(tvTit.text)
|
||||
onChanged = {
|
||||
_progress = it
|
||||
updateValue()
|
||||
this@SimpleSliderView.onChanged?.invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
FrameLayout(ctx).apply {
|
||||
setPadding(64, 0, 64, 0)
|
||||
addView(detailSeekBar, LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
okButton()
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateValue() {
|
||||
binding.tvSeekValue.text = valueFormat?.invoke(_progress) ?: _progress.toString()
|
||||
if (binding.slider.value.toInt() != _progress) {
|
||||
binding.slider.value = _progress.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val incrementRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (_progress < _max) {
|
||||
_progress++
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
handler.postDelayed(this, repeatInterval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val decrementRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (_progress > _min) {
|
||||
_progress--
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
handler.postDelayed(this, repeatInterval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
handler.removeCallbacks(incrementRunnable)
|
||||
handler.removeCallbacks(decrementRunnable)
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
|
||||
override fun setEnabled(enabled: Boolean) {
|
||||
super.setEnabled(enabled)
|
||||
tvTit.isEnabled = enabled
|
||||
binding.tvSeekValue.isEnabled = enabled
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user