Pages color filter implementation draft
parent
68dcacb918
commit
d853bb2c62
@ -0,0 +1,108 @@
|
|||||||
|
package org.koitharu.kotatsu.reader.ui.colorfilter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.LightingColorFilter
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.graphics.Insets
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import coil.ImageLoader
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import coil.size.Scale
|
||||||
|
import coil.size.ViewSizeResolver
|
||||||
|
import com.google.android.material.slider.Slider
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
|
import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPages
|
||||||
|
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||||
|
import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding
|
||||||
|
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||||
|
import org.koitharu.kotatsu.utils.ext.enqueueWith
|
||||||
|
import org.koitharu.kotatsu.utils.ext.referer
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
import com.google.android.material.R as materialR
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class ColorFilterConfigActivity : BaseActivity<ActivityColorFilterBinding>(), Slider.OnChangeListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var coil: ImageLoader
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var mangaRepositoryFacotry: MangaRepository.Factory
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(ActivityColorFilterBinding.inflate(layoutInflater))
|
||||||
|
supportActionBar?.run {
|
||||||
|
setDisplayHomeAsUpEnabled(true)
|
||||||
|
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||||
|
}
|
||||||
|
binding.sliderLightness.addOnChangeListener(this)
|
||||||
|
binding.sliderSaturation.addOnChangeListener(this)
|
||||||
|
initPreview()
|
||||||
|
updateFilter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||||
|
updateFilter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowInsetsChanged(insets: Insets) {
|
||||||
|
binding.root.updatePadding(
|
||||||
|
left = insets.left,
|
||||||
|
right = insets.right,
|
||||||
|
)
|
||||||
|
binding.scrollView.updatePadding(
|
||||||
|
bottom = insets.bottom,
|
||||||
|
)
|
||||||
|
binding.toolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
topMargin = insets.top
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateFilter() {
|
||||||
|
|
||||||
|
fun Int.toColor() = Color.rgb(this, this, this)
|
||||||
|
|
||||||
|
val cf = LightingColorFilter(
|
||||||
|
binding.sliderSaturation.value.roundToInt().toColor(),
|
||||||
|
binding.sliderLightness.value.roundToInt().toColor(),
|
||||||
|
)
|
||||||
|
binding.imageViewAfter.colorFilter = cf
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initPreview() {
|
||||||
|
val page = intent?.getParcelableExtra<ParcelableMangaPages>(EXTRA_PAGES)?.pages?.firstOrNull()
|
||||||
|
if (page == null) {
|
||||||
|
finishAfterTransition()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val repository = mangaRepositoryFacotry.create(page.source)
|
||||||
|
val url = repository.getPageUrl(page)
|
||||||
|
ImageRequest.Builder(this@ColorFilterConfigActivity)
|
||||||
|
.data(url)
|
||||||
|
.referer(page.referer)
|
||||||
|
.scale(Scale.FILL)
|
||||||
|
.size(ViewSizeResolver(binding.imageViewBefore))
|
||||||
|
.allowRgb565(false)
|
||||||
|
.target(ShadowViewTarget(binding.imageViewBefore, binding.imageViewAfter))
|
||||||
|
.enqueueWith(coil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val EXTRA_PAGES = "pages"
|
||||||
|
|
||||||
|
fun newIntent(context: Context, page: MangaPage) = Intent(context, ColorFilterConfigActivity::class.java)
|
||||||
|
.putExtra(EXTRA_PAGES, ParcelableMangaPages(listOf(page)))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package org.koitharu.kotatsu.reader.ui.colorfilter
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.widget.ImageView
|
||||||
|
import coil.target.ImageViewTarget
|
||||||
|
|
||||||
|
class ShadowViewTarget(
|
||||||
|
view: ImageView,
|
||||||
|
private val shadowView: ImageView,
|
||||||
|
) : ImageViewTarget(view) {
|
||||||
|
|
||||||
|
override var drawable: Drawable?
|
||||||
|
get() = super.drawable
|
||||||
|
set(value) {
|
||||||
|
super.drawable = value
|
||||||
|
shadowView.setImageDrawable(value?.constantState?.newDrawable())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,12 @@
|
|||||||
<vector android:autoMirrored="true" android:height="24dp"
|
<vector
|
||||||
android:tint="#000000" android:viewportHeight="24"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:width="24dp"
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
|
android:height="24dp"
|
||||||
|
android:autoMirrored="true"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
@ -0,0 +1,108 @@
|
|||||||
|
<?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_filter">
|
||||||
|
|
||||||
|
<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_marginHorizontal="@dimen/toolbar_button_margin"
|
||||||
|
android:text="@string/done" />
|
||||||
|
|
||||||
|
</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">
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/imageView_before"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
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="@sample/covers" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView_arrow"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/margin_normal"
|
||||||
|
android:src="@drawable/ic_arrow_forward"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/imageView_before"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
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:scaleType="centerCrop"
|
||||||
|
app:layout_constraintDimensionRatio="W,14:9"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/imageView_arrow"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:shapeAppearance="?shapeAppearanceCornerLarge"
|
||||||
|
app:strokeColor="?colorOutline"
|
||||||
|
app:strokeWidth="1dp"
|
||||||
|
tools:src="@sample/covers" />
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
android:id="@+id/slider_saturation"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/margin_normal"
|
||||||
|
android:value="255.0"
|
||||||
|
android:valueFrom="0.0"
|
||||||
|
android:valueTo="255.0"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/imageView_before" />
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
android:id="@+id/slider_lightness"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/margin_normal"
|
||||||
|
android:value="0.0"
|
||||||
|
android:valueFrom="0.0"
|
||||||
|
android:valueTo="255.0"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/slider_saturation" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<TextView
|
|
||||||
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="wrap_content"
|
|
||||||
android:id="@+id/textView"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:drawableEndCompat="@drawable/ic_arrow_forward"
|
|
||||||
app:drawableTint="?attr/colorPrimary"
|
|
||||||
tools:text="History" />
|
|
||||||
Loading…
Reference in New Issue