diff --git a/app/src/main/java/io/legado/app/ui/book/read/BaseReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/BaseReadBookActivity.kt index de2f930bd..0ca2cdb21 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/BaseReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/BaseReadBookActivity.kt @@ -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() + showDialogFragment() } fun showBgTextConfig() { 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 ce1888383..b61bfacca 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 @@ -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) diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt index 1718e27bf..54101661b 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt @@ -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() diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/FontSelectDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/FontSelectDialog.kt index bb8f39031..1e9131921 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/FontSelectDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/FontSelectDialog.kt @@ -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>(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" diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/InfoConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/InfoConfigDialog.kt new file mode 100644 index 000000000..8f580068b --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/book/read/config/InfoConfigDialog.kt @@ -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(EventBus.TIP_COLOR) { + upTvTipColor() + upTvTipDividerColor() + } + observeEvent>(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() + } + 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] + } + } + } + +} 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 abd9154a9..1a344ccdb 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 @@ -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) } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt index 61f4c97a9..9d244bdf7 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt @@ -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(EventBus.TIP_COLOR) { - upTvTipColor() - upTvTipDividerColor() - } observeEvent(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(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(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] - } - } } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/AccentColorButton.kt b/app/src/main/java/io/legado/app/ui/widget/AccentColorButton.kt index cba5f9675..1143050d0 100644 --- a/app/src/main/java/io/legado/app/ui/widget/AccentColorButton.kt +++ b/app/src/main/java/io/legado/app/ui/widget/AccentColorButton.kt @@ -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 { diff --git a/app/src/main/java/io/legado/app/ui/widget/SimpleSliderView.kt b/app/src/main/java/io/legado/app/ui/widget/SimpleSliderView.kt new file mode 100644 index 000000000..f44499dbd --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/SimpleSliderView.kt @@ -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 + } + +} diff --git a/app/src/main/res/drawable/ic_dottedline.xml b/app/src/main/res/drawable/ic_dottedline.xml new file mode 100644 index 000000000..efc040c3a --- /dev/null +++ b/app/src/main/res/drawable/ic_dottedline.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_underline.xml b/app/src/main/res/drawable/ic_underline.xml new file mode 100644 index 000000000..f5ee51df5 --- /dev/null +++ b/app/src/main/res/drawable/ic_underline.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/drawable/left_fade.xml b/app/src/main/res/drawable/left_fade.xml new file mode 100644 index 000000000..cc2cf9663 --- /dev/null +++ b/app/src/main/res/drawable/left_fade.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_font_select.xml b/app/src/main/res/layout/dialog_font_select.xml index 238e27902..dbfb434d0 100644 --- a/app/src/main/res/layout/dialog_font_select.xml +++ b/app/src/main/res/layout/dialog_font_select.xml @@ -5,96 +5,169 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - - + android:orientation="vertical" + android:gravity="center" + android:paddingBottom="16dp" + android:paddingHorizontal="16dp"> - + android:paddingVertical="16dp" + android:minHeight="0dp" + android:layout_gravity="center_horizontal" /> - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + android:stepSize="1" + android:valueFrom="0" + android:valueTo="20" + app:thumbHeight="24dp" + app:trackHeight="24dp" /> + + + - - - - @@ -106,27 +179,23 @@ android:layout_height="wrap_content" android:gravity="bottom"> - - - - - + android:layout_weight="1" + app:title="@string/text_indent" + app:max="4" /> - + android:layout_marginEnd="32dp" + android:layout_weight="1" + app:max="20" + app:isBottomBackground="true" + app:title="@string/paragraph_size" /> - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + @@ -239,6 +244,36 @@ + + + + + + + + - - - - - - @@ -119,7 +119,7 @@ + + - + android:layout_height="wrap_content" + android:paddingBottom="16dp"> + android:layout_marginStart="16dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> + tool:listitem="@layout/item_read_style" + app:layout_constraintStart_toEndOf="@id/cb_share_layout" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> - + + + diff --git a/app/src/main/res/layout/dialog_read_info.xml b/app/src/main/res/layout/dialog_read_info.xml new file mode 100644 index 000000000..de26e6b38 --- /dev/null +++ b/app/src/main/res/layout/dialog_read_info.xml @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_tip_config.xml b/app/src/main/res/layout/dialog_tip_config.xml index 303d48035..4bd2fa8b7 100644 --- a/app/src/main/res/layout/dialog_tip_config.xml +++ b/app/src/main/res/layout/dialog_tip_config.xml @@ -45,8 +45,9 @@ @@ -78,7 +79,7 @@ + android:gravity="end"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:textStyle="bold"/> @@ -463,9 +205,29 @@ android:checkable="true" android:text="@string/custom" /> - + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_read_style.xml b/app/src/main/res/layout/item_read_style.xml index aa3902e57..48a7ae6a9 100644 --- a/app/src/main/res/layout/item_read_style.xml +++ b/app/src/main/res/layout/item_read_style.xml @@ -9,7 +9,8 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/font_select.xml b/app/src/main/res/menu/font_select.xml deleted file mode 100644 index 44a366ef8..000000000 --- a/app/src/main/res/menu/font_select.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values-zh/arrays.xml b/app/src/main/res/values-zh/arrays.xml index 5bc1afd4b..7cc18d2d2 100644 --- a/app/src/main/res/values-zh/arrays.xml +++ b/app/src/main/res/values-zh/arrays.xml @@ -112,7 +112,7 @@ - 跟随内容 + 跟随正文字体颜色 自定义 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index a57fe920a..4b00ce64c 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -266,7 +266,7 @@ 拷贝内容 一键缓存 这是一段测试文字\n\u3000\u3000只是让你看看效果的 - 文字颜色和背景(长按自定义) + 背景 沉浸式状态栏 还剩 %d 章未下载 长按输入颜色值 @@ -817,7 +817,7 @@ 无操作 正文标题 显示/隐藏 - 页眉页脚 + 页眉与页脚 规则订阅 添加大佬们提供的规则导入地址\n添加后点击可导入规则 拉取云端进度 @@ -1331,4 +1331,8 @@ 折叠所有卷 展开所有卷 自定义 + 全局设置 + 字体样式 + 阴影样式 + 长按自定义 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 795cd00de..1ee291464 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1332,4 +1332,8 @@ 折叠所有卷 展开所有卷 自定义 + 全局设置 + 字体样式 + 阴影样式 + 长按自定义