增加亮度和图片滤镜 (#4813)
Some checks are pending
Test Build / prepare (push) Waiting to run
Test Build / build (app, release) (push) Blocked by required conditions
Test Build / build (app, releaseA) (push) Blocked by required conditions
Test Build / prerelease (push) Blocked by required conditions
Test Build / lanzou (push) Blocked by required conditions
Test Build / test_Branch (push) Blocked by required conditions
Test Build / telegram (push) Blocked by required conditions

* 增加亮度和图片滤镜

* ...

* ...

* ...
This commit is contained in:
lhjgege
2025-03-13 11:42:06 +08:00
committed by GitHub
parent 0b18832803
commit 0403a34c6f
18 changed files with 336 additions and 2 deletions

View File

@@ -100,6 +100,7 @@ object PreferKey {
const val mangaFooterConfig = "mangaFooterConfig"
const val disableClickScroll = "disableClickScroll"
const val enableMangaHorizontalScroll = "enableMangaHorizontalScroll"
const val mangaColorFilter = "mangaColorFilter"
const val autoRefresh = "auto_refresh"
const val defaultToRead = "defaultToRead"
const val exportCharset = "exportCharset"

View File

@@ -650,5 +650,11 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
set(value) {
appCtx.putPrefBoolean(PreferKey.enableMangaHorizontalScroll, value)
}
var mangaColorFilter
get() = appCtx.getPrefString(PreferKey.mangaColorFilter, "")
set(value) {
appCtx.putPrefString(PreferKey.mangaColorFilter, value)
}
}

View File

@@ -21,6 +21,7 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.globalExecutor
import io.legado.app.model.webBook.WebBook
import io.legado.app.ui.book.manga.config.MangaColorFilterConfig
import io.legado.app.ui.book.manga.entities.MangaChapter
import io.legado.app.ui.book.manga.entities.MangaContent
import io.legado.app.ui.book.manga.entities.MangaContentData
@@ -597,5 +598,6 @@ object ReadManga : CoroutineScope by MainScope() {
fun loadFail(msg: String)
fun sureNewProgress(progress: BookProgress)
fun showLoading()
fun colorFilter(config: MangaColorFilterConfig)
}
}

View File

@@ -42,6 +42,8 @@ import io.legado.app.model.ReadManga
import io.legado.app.receiver.NetworkChangedListener
import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.manga.config.MangaColorFilterConfig
import io.legado.app.ui.book.manga.config.MangaColorFilterDialog
import io.legado.app.ui.book.manga.config.MangaFooterConfig
import io.legado.app.ui.book.manga.config.MangaFooterSettingDialog
import io.legado.app.ui.book.manga.entities.MangaContent
@@ -97,6 +99,11 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
AppConfig.mangaAutoPageSpeed
}
private val mMangaColorFilter: MangaColorFilterConfig by lazy {
GSON.fromJsonObject<MangaColorFilterConfig>(AppConfig.mangaColorFilter).getOrNull()
?: MangaColorFilterConfig()
}
private var mMangaAutoPageSpeed = mInitMangaAutoPageSpeed
private lateinit var mMangaFooterConfig: MangaFooterConfig
private val mLabelBuilder by lazy { StringBuilder() }
@@ -190,7 +197,10 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
}
private fun initRecyclerView() {
mAdapter.isHorizontal = AppConfig.enableMangaHorizontalScroll
mAdapter.run {
isHorizontal = AppConfig.enableMangaHorizontalScroll
setMangaImageColorFilter(mMangaColorFilter)
}
binding.mRecyclerManga.run {
adapter = mAdapter
itemAnimator = null
@@ -418,6 +428,12 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
}
}
override fun colorFilter(config: MangaColorFilterConfig) {
mAdapter.setMangaImageColorFilter(config)
mAdapter.notifyItemChanged(ReadManga.durChapterPos)
updateWindowBrightness(config.l)
}
override val oldBook: Book?
get() = ReadManga.book
@@ -527,6 +543,10 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
mAdapter.getCurrentList().size
)
}
R.id.menu_manga_color_filter -> {
MangaColorFilterDialog().show(supportFragmentManager, "MangaColorFilterDialog")
}
}
return super.onCompatOptionsItemSelected(item)
}
@@ -717,4 +737,13 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
return (mLayoutManager.findLastCompletelyVisibleItemPosition() == adapter.itemCount - 1) &&
!canScrollVertically(1)
}
fun updateWindowBrightness(brightness: Int) {
val layoutParams = window.attributes
val normalizedBrightness = brightness.toFloat() / 255.0f
layoutParams.screenBrightness = normalizedBrightness.coerceIn(0f, 1f)
window.attributes = layoutParams
// 强制刷新屏幕
window.decorView.postInvalidate()
}
}

View File

@@ -0,0 +1,14 @@
package io.legado.app.ui.book.manga.config
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class MangaColorFilterConfig(
var r: Int = 0,
var g: Int = 0,
var b: Int = 0,
var a: Int = 0,
var l: Int = 0
) :
Parcelable

View File

@@ -0,0 +1,127 @@
package io.legado.app.ui.book.manga.config
import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import io.legado.app.R
import io.legado.app.base.BaseDialogFragment
import io.legado.app.databinding.DialogMangaColorFilterBinding
import io.legado.app.help.config.AppConfig
import io.legado.app.model.ReadManga
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.setLayout
import io.legado.app.utils.viewbindingdelegate.viewBinding
class MangaColorFilterDialog : BaseDialogFragment(R.layout.dialog_manga_color_filter) {
private val binding by viewBinding(DialogMangaColorFilterBinding::bind)
private val mConfig =
GSON.fromJsonObject<MangaColorFilterConfig>(AppConfig.mangaColorFilter).getOrNull()
?: MangaColorFilterConfig()
override fun onStart() {
super.onStart()
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
binding.seekA.progress = mConfig.a
binding.seekBrightness.progress = mConfig.l
binding.seekB.progress = mConfig.b
binding.seekG.progress = mConfig.g
binding.seekR.progress = mConfig.r
binding.seekBrightness.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
mConfig.l = progress
ReadManga.mCallback?.colorFilter(mConfig)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
binding.seekR.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
mConfig.r = progress
ReadManga.mCallback?.colorFilter(mConfig)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
binding.seekG.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
mConfig.g = progress
ReadManga.mCallback?.colorFilter(mConfig)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
binding.seekB.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
mConfig.b = progress
ReadManga.mCallback?.colorFilter(mConfig)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
binding.seekA.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar?,
progress: Int,
fromUser: Boolean
) {
mConfig.a = progress
ReadManga.mCallback?.colorFilter(mConfig)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
})
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
AppConfig.mangaColorFilter = GSON.toJson(mConfig)
}
}

View File

@@ -1,6 +1,8 @@
package io.legado.app.ui.book.manga.recyclerview
import android.content.Context
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.ViewGroup
@@ -22,6 +24,7 @@ import io.legado.app.databinding.BookComicRvBinding
import io.legado.app.help.glide.progress.ProgressManager
import io.legado.app.model.BookCover
import io.legado.app.model.ReadManga
import io.legado.app.ui.book.manga.config.MangaColorFilterConfig
import io.legado.app.ui.book.manga.entities.MangaContent
import io.legado.app.ui.book.manga.entities.ReaderLoading
import io.legado.app.utils.getCompatDrawable
@@ -32,6 +35,7 @@ class MangaAdapter(private val context: Context) :
RecyclerView.Adapter<RecyclerView.ViewHolder>(), PreloadModelProvider<Any> {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private lateinit var mConfig: MangaColorFilterConfig
companion object {
private const val LOADING_VIEW = 0
@@ -95,8 +99,24 @@ class MangaAdapter(private val context: Context) :
}
fun onBind(item: MangaContent) {
setImageColorFilter()
loadImageWithRetry(item.mImageUrl, isHorizontal, item.imageCount == 1)
}
fun setImageColorFilter() {
binding.image.run {
require(mConfig.r in 0..255 && mConfig.g in 0..255 && mConfig.b in 0..255 && mConfig.a in 0..255) {
"ARGB values must be between 0-255"
}
val matrix = floatArrayOf(
(255 - mConfig.r) / 255f, 0f, 0f, 0f, 0f,
0f, (255 - mConfig.g) / 255f, 0f, 0f, 0f,
0f, 0f, (255 - mConfig.b) / 255f, 0f, 0f,
0f, 0f, 0f, (255 - mConfig.a) / 255f, 0f
)
colorFilter = ColorMatrixColorFilter(ColorMatrix(matrix))
}
}
}
inner class PageMoreViewHolder(val binding: BookComicLoadingRvBinding) :
@@ -209,4 +229,8 @@ class MangaAdapter(private val context: Context) :
}
return null
}
fun setMangaImageColorFilter(config: MangaColorFilterConfig) {
mConfig = config
}
}

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<io.legado.app.ui.widget.text.AccentTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="滤镜"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/brightness"
android:textColor="@color/primaryText"
android:textSize="14sp" />
<io.legado.app.lib.theme.view.ThemeSeekBar
android:id="@+id/seek_brightness"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:max="255" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="R"
android:textColor="@color/primaryText"
android:textSize="14sp" />
<io.legado.app.lib.theme.view.ThemeSeekBar
android:id="@+id/seek_R"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:max="255" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="G"
android:textColor="@color/primaryText"
android:textSize="14sp" />
<io.legado.app.lib.theme.view.ThemeSeekBar
android:id="@+id/seek_g"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:max="255" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="B"
android:textColor="@color/primaryText"
android:textSize="14sp" />
<io.legado.app.lib.theme.view.ThemeSeekBar
android:id="@+id/seek_b"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:max="255" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="A"
android:textColor="@color/primaryText"
android:textSize="14sp" />
<io.legado.app.lib.theme.view.ThemeSeekBar
android:id="@+id/seek_a"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:max="255" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -19,7 +19,8 @@
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle">
android:theme="?attr/actionBarStyle"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/title_bar_addition"

View File

@@ -68,4 +68,10 @@
android:id="@+id/menu_manga_footer_config"
android:title="@string/manga_footer_config"
app:showAsAction="never" />
<item
android:id="@+id/menu_manga_color_filter"
android:title="@string/manga_color_filter"
app:showAsAction="never" />
</menu>

View File

@@ -1205,4 +1205,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1208,4 +1208,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1208,4 +1208,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1204,4 +1204,5 @@ Còn </string>
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1205,4 +1205,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1207,4 +1207,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1207,4 +1207,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>

View File

@@ -1208,4 +1208,5 @@
<string name="manga_radio_left">靠左</string>
<string name="manga_radio_center">居中</string>
<string name="enable_manga_horizontal_scroll">水平滚动</string>
<string name="manga_color_filter">滤镜</string>
</resources>