Color inversion in pages color filter #372
This commit is contained in:
@@ -24,6 +24,7 @@ import org.koitharu.kotatsu.core.db.migrations.Migration11To12
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration12To13
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration13To14
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration14To15
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration15To16
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration1To2
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration2To3
|
||||
import org.koitharu.kotatsu.core.db.migrations.Migration3To4
|
||||
@@ -48,7 +49,7 @@ import org.koitharu.kotatsu.tracker.data.TrackEntity
|
||||
import org.koitharu.kotatsu.tracker.data.TrackLogEntity
|
||||
import org.koitharu.kotatsu.tracker.data.TracksDao
|
||||
|
||||
const val DATABASE_VERSION = 15
|
||||
const val DATABASE_VERSION = 16
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
@@ -100,6 +101,7 @@ val databaseMigrations: Array<Migration>
|
||||
Migration12To13(),
|
||||
Migration13To14(),
|
||||
Migration14To15(),
|
||||
Migration15To16(),
|
||||
)
|
||||
|
||||
fun MangaDatabase(context: Context): MangaDatabase = Room
|
||||
|
||||
@@ -23,4 +23,5 @@ data class MangaPrefsEntity(
|
||||
@ColumnInfo(name = "mode") val mode: Int,
|
||||
@ColumnInfo(name = "cf_brightness") val cfBrightness: Float,
|
||||
@ColumnInfo(name = "cf_contrast") val cfContrast: Float,
|
||||
@ColumnInfo(name = "cf_invert") val cfInvert: Boolean,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.koitharu.kotatsu.core.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration15To16 : Migration(15, 16) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE preferences ADD COLUMN `cf_invert` INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,12 @@ import dagger.Reusable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.toEntities
|
||||
import org.koitharu.kotatsu.core.db.entity.toEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.toManga
|
||||
import org.koitharu.kotatsu.core.db.entity.toMangaTags
|
||||
import org.koitharu.kotatsu.core.network.MangaHttpClient
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
@@ -22,7 +20,6 @@ import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class MangaDataRepository @Inject constructor(
|
||||
@MangaHttpClient private val okHttpClient: OkHttpClient,
|
||||
private val db: MangaDatabase,
|
||||
) {
|
||||
|
||||
@@ -42,6 +39,7 @@ class MangaDataRepository @Inject constructor(
|
||||
entity.copy(
|
||||
cfBrightness = colorFilter?.brightness ?: 0f,
|
||||
cfContrast = colorFilter?.contrast ?: 0f,
|
||||
cfInvert = colorFilter?.isInverted ?: false,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -84,8 +82,8 @@ class MangaDataRepository @Inject constructor(
|
||||
}
|
||||
|
||||
private fun MangaPrefsEntity.getColorFilterOrNull(): ReaderColorFilter? {
|
||||
return if (cfBrightness != 0f || cfContrast != 0f) {
|
||||
ReaderColorFilter(cfBrightness, cfContrast)
|
||||
return if (cfBrightness != 0f || cfContrast != 0f || cfInvert) {
|
||||
ReaderColorFilter(cfBrightness, cfContrast, cfInvert)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -96,5 +94,6 @@ class MangaDataRepository @Inject constructor(
|
||||
mode = -1,
|
||||
cfBrightness = 0f,
|
||||
cfContrast = 0f,
|
||||
cfInvert = false,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,35 +6,27 @@ import android.graphics.ColorMatrixColorFilter
|
||||
class ReaderColorFilter(
|
||||
val brightness: Float,
|
||||
val contrast: Float,
|
||||
val isInverted: Boolean,
|
||||
) {
|
||||
|
||||
val isEmpty: Boolean
|
||||
get() = brightness == 0f && contrast == 0f
|
||||
get() = !isInverted && brightness == 0f && contrast == 0f
|
||||
|
||||
fun toColorFilter(): ColorMatrixColorFilter {
|
||||
val cm = ColorMatrix()
|
||||
val scale = brightness + 1f
|
||||
cm.setScale(scale, scale, scale, 1f)
|
||||
if (isInverted) {
|
||||
cm.inverted()
|
||||
}
|
||||
cm.setBrightness(brightness)
|
||||
cm.setContrast(contrast)
|
||||
return ColorMatrixColorFilter(cm)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ReaderColorFilter
|
||||
|
||||
if (brightness != other.brightness) return false
|
||||
if (contrast != other.contrast) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = brightness.hashCode()
|
||||
result = 31 * result + contrast.hashCode()
|
||||
return result
|
||||
private fun ColorMatrix.setBrightness(brightness: Float) {
|
||||
val scale = brightness + 1f
|
||||
val matrix = ColorMatrix()
|
||||
matrix.setScale(scale, scale, scale, 1f)
|
||||
postConcat(matrix)
|
||||
}
|
||||
|
||||
private fun ColorMatrix.setContrast(contrast: Float) {
|
||||
@@ -49,4 +41,32 @@ class ReaderColorFilter(
|
||||
val matrix = ColorMatrix(array)
|
||||
postConcat(matrix)
|
||||
}
|
||||
|
||||
private fun ColorMatrix.inverted() {
|
||||
val matrix = floatArrayOf(
|
||||
-1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||
)
|
||||
set(matrix)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ReaderColorFilter
|
||||
|
||||
if (brightness != other.brightness) return false
|
||||
if (contrast != other.contrast) return false
|
||||
return isInverted == other.isInverted
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = brightness.hashCode()
|
||||
result = 31 * result + contrast.hashCode()
|
||||
result = 31 * result + isInverted.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.content.res.Resources
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CompoundButton
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.updateLayoutParams
|
||||
@@ -26,6 +27,7 @@ import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.core.util.ext.indicator
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.core.util.ext.setChecked
|
||||
import org.koitharu.kotatsu.core.util.ext.setValueRounded
|
||||
import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
@@ -39,7 +41,7 @@ import com.google.android.material.R as materialR
|
||||
class ColorFilterConfigActivity :
|
||||
BaseActivity<ActivityColorFilterBinding>(),
|
||||
Slider.OnChangeListener,
|
||||
View.OnClickListener {
|
||||
View.OnClickListener, CompoundButton.OnCheckedChangeListener {
|
||||
|
||||
@Inject
|
||||
lateinit var coil: ImageLoader
|
||||
@@ -58,6 +60,7 @@ class ColorFilterConfigActivity :
|
||||
val formatter = PercentLabelFormatter(resources)
|
||||
viewBinding.sliderContrast.setLabelFormatter(formatter)
|
||||
viewBinding.sliderBrightness.setLabelFormatter(formatter)
|
||||
viewBinding.switchInvert.setOnCheckedChangeListener(this)
|
||||
viewBinding.buttonDone.setOnClickListener(this)
|
||||
viewBinding.buttonReset.setOnClickListener(this)
|
||||
|
||||
@@ -80,6 +83,10 @@ class ColorFilterConfigActivity :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
|
||||
viewModel.setInversion(isChecked)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.button_done -> viewModel.save()
|
||||
@@ -103,13 +110,14 @@ class ColorFilterConfigActivity :
|
||||
private fun onColorFilterChanged(readerColorFilter: ReaderColorFilter?) {
|
||||
viewBinding.sliderBrightness.setValueRounded(readerColorFilter?.brightness ?: 0f)
|
||||
viewBinding.sliderContrast.setValueRounded(readerColorFilter?.contrast ?: 0f)
|
||||
viewBinding.switchInvert.setChecked(readerColorFilter?.isInverted ?: false, false)
|
||||
viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter()
|
||||
}
|
||||
|
||||
private fun onPreviewChanged(preview: MangaPage?) {
|
||||
if (preview == null) return
|
||||
ImageRequest.Builder(this@ColorFilterConfigActivity)
|
||||
.data(preview.url)
|
||||
.data(preview)
|
||||
.scale(Scale.FILL)
|
||||
.decodeRegion()
|
||||
.tag(preview.source)
|
||||
@@ -117,7 +125,7 @@ class ColorFilterConfigActivity :
|
||||
.error(R.drawable.ic_error_placeholder)
|
||||
.size(ViewSizeResolver(viewBinding.imageViewBefore))
|
||||
.allowRgb565(false)
|
||||
.target(ShadowViewTarget(viewBinding.imageViewBefore, viewBinding.imageViewAfter))
|
||||
.target(DoubleViewTarget(viewBinding.imageViewBefore, viewBinding.imageViewAfter))
|
||||
.enqueueWith(coil)
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,32 @@ class ColorFilterConfigViewModel @Inject constructor(
|
||||
|
||||
fun setBrightness(brightness: Float) {
|
||||
val cf = colorFilter.value
|
||||
colorFilter.value = ReaderColorFilter(brightness, cf?.contrast ?: 0f).takeUnless { it.isEmpty }
|
||||
colorFilter.value = ReaderColorFilter(
|
||||
brightness = brightness,
|
||||
contrast = cf?.contrast ?: 0f,
|
||||
isInverted = cf?.isInverted ?: false,
|
||||
).takeUnless { it.isEmpty }
|
||||
}
|
||||
|
||||
fun setContrast(contrast: Float) {
|
||||
val cf = colorFilter.value
|
||||
colorFilter.value = ReaderColorFilter(cf?.brightness ?: 0f, contrast).takeUnless { it.isEmpty }
|
||||
colorFilter.value = ReaderColorFilter(
|
||||
brightness = cf?.brightness ?: 0f,
|
||||
contrast = contrast,
|
||||
isInverted = cf?.isInverted ?: false,
|
||||
).takeUnless { it.isEmpty }
|
||||
}
|
||||
|
||||
fun setInversion(invert: Boolean) {
|
||||
val cf = colorFilter.value
|
||||
if (invert == cf?.isInverted) {
|
||||
return
|
||||
}
|
||||
colorFilter.value = ReaderColorFilter(
|
||||
brightness = cf?.brightness ?: 0f,
|
||||
contrast = cf?.contrast ?: 0f,
|
||||
isInverted = invert,
|
||||
).takeUnless { it.isEmpty }
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
|
||||
@@ -4,15 +4,15 @@ import android.graphics.drawable.Drawable
|
||||
import android.widget.ImageView
|
||||
import coil.target.ImageViewTarget
|
||||
|
||||
class ShadowViewTarget(
|
||||
view: ImageView,
|
||||
private val shadowView: ImageView,
|
||||
) : ImageViewTarget(view) {
|
||||
class DoubleViewTarget(
|
||||
primaryView: ImageView,
|
||||
private val secondaryView: ImageView,
|
||||
) : ImageViewTarget(primaryView) {
|
||||
|
||||
override var drawable: Drawable?
|
||||
get() = super.drawable
|
||||
set(value) {
|
||||
super.drawable = value
|
||||
shadowView.setImageDrawable(value?.constantState?.newDrawable())
|
||||
secondaryView.setImageDrawable(value?.constantState?.newDrawable())
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class ReaderSettings(
|
||||
get() = settings.zoomMode
|
||||
|
||||
val colorFilter: ReaderColorFilter?
|
||||
get() = colorFilterFlow.value
|
||||
get() = colorFilterFlow.value?.takeUnless { it.isEmpty }
|
||||
|
||||
val isPagesNumbersEnabled: Boolean
|
||||
get() = settings.isPagesNumbersEnabled
|
||||
|
||||
196
app/src/main/res/layout-w600dp/activity_color_filter.xml
Normal file
196
app/src/main/res/layout-w600dp/activity_color_filter.xml
Normal file
@@ -0,0 +1,196 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
tools:navigationIcon="@drawable/abc_ic_clear_material"
|
||||
tools:title="@string/color_correction">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_done"
|
||||
style="@style/Widget.Material3.Button.UnelevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="@dimen/toolbar_button_margin"
|
||||
android:text="@string/done" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_reset"
|
||||
style="?materialButtonOutlinedStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginHorizontal="@dimen/toolbar_button_margin"
|
||||
android:text="@string/reset" />
|
||||
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="ifContentScrolls">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_normal">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/imageView_before"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:padding="2dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintDimensionRatio="W,14:9"
|
||||
app:layout_constraintEnd_toStartOf="@id/imageView_arrow"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearance="?shapeAppearanceCornerLarge"
|
||||
app:strokeColor="?colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progress_before"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/imageView_before"
|
||||
app:layout_constraintEnd_toEndOf="@id/imageView_before"
|
||||
app:layout_constraintStart_toStartOf="@id/imageView_before"
|
||||
app:layout_constraintTop_toTopOf="@id/imageView_before" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:padding="@dimen/margin_normal"
|
||||
android:src="@drawable/ic_arrow_forward"
|
||||
app:layout_constraintBottom_toBottomOf="@id/imageView_before"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/imageView_before" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/imageView_after"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:padding="2dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintDimensionRatio="W,14:9"
|
||||
app:layout_constraintEnd_toStartOf="@id/guideline_vertical"
|
||||
app:layout_constraintStart_toEndOf="@id/imageView_arrow"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:shapeAppearance="?shapeAppearanceCornerLarge"
|
||||
app:strokeColor="?colorOutline"
|
||||
app:strokeWidth="1dp"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progress_after"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/imageView_after"
|
||||
app:layout_constraintEnd_toEndOf="@id/imageView_after"
|
||||
app:layout_constraintStart_toStartOf="@id/imageView_after"
|
||||
app:layout_constraintTop_toTopOf="@id/imageView_after" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_invert"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:text="@string/invert_colors"
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_brightness"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginTop="@dimen/margin_normal"
|
||||
android:text="@string/brightness"
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/switch_invert" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_brightness"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginTop="@dimen/margin_small"
|
||||
android:labelFor="@id/textView_brightness"
|
||||
android:value="0.0"
|
||||
android:valueFrom="-1.0"
|
||||
android:valueTo="1.0"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/textView_brightness" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_contrast"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginTop="@dimen/margin_small"
|
||||
android:text="@string/contrast"
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/slider_brightness" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_contrast"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginTop="@dimen/margin_small"
|
||||
android:value="0.0"
|
||||
android:valueFrom="-1.0"
|
||||
android:valueTo="1.0"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/textView_contrast" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_normal"
|
||||
android:layout_marginTop="@dimen/margin_normal"
|
||||
android:text="@string/color_correction_hint"
|
||||
android:textAppearance="?textAppearanceBodySmall"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline_vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/slider_contrast" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -100,6 +100,17 @@
|
||||
app:layout_constraintStart_toStartOf="@id/imageView_after"
|
||||
app:layout_constraintTop_toTopOf="@id/imageView_after" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/switch_invert"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/invert_colors"
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/imageView_before" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_brightness"
|
||||
android:layout_width="0dp"
|
||||
@@ -109,7 +120,7 @@
|
||||
android:textAppearance="?textAppearanceTitleMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/imageView_before" />
|
||||
app:layout_constraintTop_toBottomOf="@id/switch_invert" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/slider_brightness"
|
||||
|
||||
@@ -428,4 +428,5 @@
|
||||
<string name="downloaded">Downloaded</string>
|
||||
<string name="images_proxy_title">Images optimization proxy</string>
|
||||
<string name="images_procy_description">Use the wsrv.nl service to reduce traffic usage and speed up image loading if possible</string>
|
||||
<string name="invert_colors">Invert colors</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user