mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-20 01:59:17 +01:00
Adding blur to overflow dialog + manga cover blur on tap
This commit is contained in:
parent
cbf7e116d7
commit
63f5cfee3a
@ -26,6 +26,7 @@ import android.webkit.WebView
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.net.toUri
|
||||
@ -79,6 +80,7 @@ import eu.kanade.tachiyomi.util.system.hasSideNavBar
|
||||
import eu.kanade.tachiyomi.util.system.isBottomTappable
|
||||
import eu.kanade.tachiyomi.util.system.launchUI
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.blurBehindWindow
|
||||
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
|
||||
import eu.kanade.tachiyomi.util.view.getItemView
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
@ -750,9 +752,12 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
||||
if (overflowDialog != null) return false
|
||||
val overflowDialog = OverflowDialog(this)
|
||||
this.overflowDialog = overflowDialog
|
||||
overflowDialog.setOnDismissListener {
|
||||
this.overflowDialog = null
|
||||
}
|
||||
overflowDialog.blurBehindWindow(
|
||||
window,
|
||||
onDismiss = {
|
||||
this.overflowDialog = null
|
||||
}
|
||||
)
|
||||
overflowDialog.show()
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.main
|
||||
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||
@ -25,7 +26,7 @@ class OverflowDialog(activity: MainActivity) : Dialog(activity, R.style.Overflow
|
||||
setContentView(binding.root)
|
||||
|
||||
binding.touchOutside.setOnClickListener {
|
||||
dismiss()
|
||||
cancel()
|
||||
}
|
||||
val incogText = context.getString(R.string.incognito_mode)
|
||||
with(binding.incognitoModeItem) {
|
||||
@ -83,7 +84,7 @@ class OverflowDialog(activity: MainActivity) : Dialog(activity, R.style.Overflow
|
||||
window.decorView.fitsSystemWindows = true
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility
|
||||
.rem(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility
|
||||
.rem(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@ -1465,9 +1467,11 @@ class MangaDetailsController :
|
||||
rightMargin = defMargin
|
||||
bottomMargin = defMargin + binding.recycler.paddingBottom
|
||||
}
|
||||
val shortAnimationDuration = resources?.getInteger(
|
||||
android.R.integer.config_shortAnimTime
|
||||
) ?: 0
|
||||
val shortAnimationDuration = (
|
||||
resources?.getInteger(
|
||||
android.R.integer.config_shortAnimTime
|
||||
) ?: 0
|
||||
).toLong()
|
||||
|
||||
// TransitionSet for the full cover because using animation for this SUCKS
|
||||
val transitionSet = TransitionSet()
|
||||
@ -1475,7 +1479,7 @@ class MangaDetailsController :
|
||||
transitionSet.addTransition(bound)
|
||||
val changeImageTransform = ChangeImageTransform()
|
||||
transitionSet.addTransition(changeImageTransform)
|
||||
transitionSet.duration = shortAnimationDuration.toLong()
|
||||
transitionSet.duration = shortAnimationDuration
|
||||
TransitionManager.beginDelayedTransition(binding.frameLayout, transitionSet)
|
||||
|
||||
// AnimationSet for backdrop because idk how to use TransitionSet
|
||||
@ -1483,7 +1487,18 @@ class MangaDetailsController :
|
||||
play(
|
||||
ObjectAnimator.ofFloat(fullBackdrop, View.ALPHA, 0f, 0.5f)
|
||||
)
|
||||
duration = shortAnimationDuration.toLong()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
binding.swipeRefresh.setRenderEffect(
|
||||
RenderEffect.createBlurEffect(
|
||||
15f,
|
||||
15f,
|
||||
Shader.TileMode.MIRROR
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
duration = shortAnimationDuration
|
||||
interpolator = DecelerateInterpolator()
|
||||
addListener(
|
||||
object : AnimatorListenerAdapter() {
|
||||
@ -1524,13 +1539,16 @@ class MangaDetailsController :
|
||||
transitionSet2.addTransition(bound2)
|
||||
val changeImageTransform2 = ChangeImageTransform()
|
||||
transitionSet2.addTransition(changeImageTransform2)
|
||||
transitionSet2.duration = shortAnimationDuration.toLong()
|
||||
transitionSet2.duration = shortAnimationDuration
|
||||
TransitionManager.beginDelayedTransition(binding.frameLayout, transitionSet2)
|
||||
|
||||
// Animation to remove backdrop and hide the full cover
|
||||
currentAnimator = AnimatorSet().apply {
|
||||
play(ObjectAnimator.ofFloat(fullBackdrop, View.ALPHA, 0f))
|
||||
duration = shortAnimationDuration.toLong()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
binding.swipeRefresh.setRenderEffect(null)
|
||||
}
|
||||
duration = shortAnimationDuration
|
||||
interpolator = DecelerateInterpolator()
|
||||
|
||||
if (!activity.isInNightMode()) {
|
||||
|
@ -2,32 +2,42 @@
|
||||
|
||||
package eu.kanade.tachiyomi.util.view
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.Point
|
||||
import android.graphics.RenderEffect
|
||||
import android.graphics.Shader
|
||||
import android.os.Build
|
||||
import android.view.Gravity
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.Window
|
||||
import android.view.WindowInsets
|
||||
import android.widget.Button
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.Px
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.view.menu.MenuBuilder
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsAnimationCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.forEach
|
||||
import androidx.interpolator.view.animation.FastOutLinearInInterpolator
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -45,7 +55,6 @@ import eu.kanade.tachiyomi.util.system.contextCompatColor
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.system.pxToDp
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
@ -412,3 +421,54 @@ inline fun View.popupMenu(
|
||||
popup.show()
|
||||
return popup
|
||||
}
|
||||
|
||||
fun Dialog.blurBehindWindow(
|
||||
window: Window?,
|
||||
blurAmount: Float = 20f,
|
||||
onShow: DialogInterface.OnShowListener? = null,
|
||||
onDismiss: DialogInterface.OnDismissListener? = null,
|
||||
onCancel: DialogInterface.OnCancelListener? = null
|
||||
) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
setOnShowListener {
|
||||
onShow?.onShow(it)
|
||||
window?.decorView?.animateBlur(1f, blurAmount, 50)?.start()
|
||||
}
|
||||
setOnDismissListener {
|
||||
onDismiss?.onDismiss(it)
|
||||
window?.decorView?.animateBlur(blurAmount, 1f, 50, true)?.start()
|
||||
}
|
||||
setOnCancelListener {
|
||||
onCancel?.onCancel(it)
|
||||
window?.decorView?.animateBlur(blurAmount, 1f, 50, true)?.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(31)
|
||||
fun View.animateBlur(
|
||||
@FloatRange(from = 0.1) from: Float,
|
||||
@FloatRange(from = 0.1) to: Float,
|
||||
duration: Long,
|
||||
removeBlurAtEnd: Boolean = false
|
||||
): ValueAnimator {
|
||||
return ValueAnimator.ofFloat(from, to).apply {
|
||||
interpolator = FastOutLinearInInterpolator()
|
||||
this.duration = duration
|
||||
addUpdateListener { animator ->
|
||||
val amount = animator.animatedValue as Float
|
||||
try {
|
||||
setRenderEffect(
|
||||
RenderEffect.createBlurEffect(amount, amount, Shader.TileMode.CLAMP)
|
||||
)
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
if (removeBlurAtEnd) {
|
||||
addListener(
|
||||
onEnd = {
|
||||
setRenderEffect(null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user