ui: use material transitions on some shapes

These look a lot better than the old ones.
This commit is contained in:
Alexander Capehart 2024-05-18 23:16:09 -06:00
parent e809b2875e
commit f742aa7592
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
3 changed files with 83 additions and 27 deletions

View file

@ -31,15 +31,17 @@ import android.view.WindowInsets
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.R as MR
import com.google.android.material.motion.MotionUtils
import kotlin.math.abs import kotlin.math.abs
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.list.recycler.AuxioRecyclerView import org.oxycblt.auxio.list.recycler.AuxioRecyclerView
import org.oxycblt.auxio.util.getDimenPixels import org.oxycblt.auxio.util.getDimenPixels
import org.oxycblt.auxio.util.getDrawableCompat import org.oxycblt.auxio.util.getDrawableCompat
import org.oxycblt.auxio.util.getInteger
import org.oxycblt.auxio.util.isRtl import org.oxycblt.auxio.util.isRtl
import org.oxycblt.auxio.util.isUnder import org.oxycblt.auxio.util.isUnder
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
@ -79,10 +81,28 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
// Thumb // Thumb
private val thumbView = private val thumbView =
View(context).apply { View(context).apply {
alpha = 0f scaleX = 0f
background = context.getDrawableCompat(R.drawable.ui_scroll_thumb) background = context.getDrawableCompat(R.drawable.ui_scroll_thumb)
} }
private val thumbEnterInterpolator =
MotionUtils.resolveThemeInterpolator(
context,
MR.attr.motionEasingEmphasizedDecelerateInterpolator,
FastOutSlowInInterpolator())
private val thumbEnterDuration =
MotionUtils.resolveThemeDuration(context, MR.attr.motionDurationShort4, 300)
private val thumbExitInterpolator =
MotionUtils.resolveThemeInterpolator(
context,
MR.attr.motionEasingEmphasizedAccelerateInterpolator,
FastOutSlowInInterpolator())
private val thumbExitDuration =
MotionUtils.resolveThemeDuration(context, MR.attr.motionDurationShort2, 100)
private val thumbWidth = thumbView.background.intrinsicWidth private val thumbWidth = thumbView.background.intrinsicWidth
private val thumbHeight = thumbView.background.intrinsicHeight private val thumbHeight = thumbView.background.intrinsicHeight
private val thumbPadding = Rect(0, 0, 0, 0) private val thumbPadding = Rect(0, 0, 0, 0)
@ -98,6 +118,9 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
// Popup // Popup
private val popupView = private val popupView =
FastScrollPopupView(context).apply { FastScrollPopupView(context).apply {
scaleX = 0f
scaleY = 0f
alpha = 0f
layoutParams = layoutParams =
FrameLayout.LayoutParams( FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
@ -107,6 +130,24 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
} }
private val popupEnterInterpolator =
MotionUtils.resolveThemeInterpolator(
context,
MR.attr.motionEasingEmphasizedDecelerateInterpolator,
FastOutSlowInInterpolator())
private val popupEnterDuration =
MotionUtils.resolveThemeDuration(context, MR.attr.motionDurationMedium1, 300)
private val popupExitInterpolator =
MotionUtils.resolveThemeInterpolator(
context,
MR.attr.motionEasingEmphasizedAccelerateInterpolator,
FastOutSlowInInterpolator())
private val popupExitDuration =
MotionUtils.resolveThemeDuration(context, MR.attr.motionDurationShort2, 100)
private var showingPopup = false private var showingPopup = false
// Touch // Touch
@ -417,7 +458,12 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
showingThumb = true showingThumb = true
animateViewIn(thumbView) thumbView
.animate()
.scaleX(1f)
.setInterpolator(thumbEnterInterpolator)
.setDuration(thumbEnterDuration.toLong())
.start()
} }
private fun hideScrollbar() { private fun hideScrollbar() {
@ -426,7 +472,12 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
showingThumb = false showingThumb = false
animateViewOut(thumbView) thumbView
.animate()
.scaleX(0f)
.setInterpolator(thumbExitInterpolator)
.setDuration(thumbExitDuration.toLong())
.start()
} }
private fun showPopup() { private fun showPopup() {
@ -434,8 +485,18 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
return return
} }
popupView.scaleX = 0f
popupView.scaleY = 0f
popupView.alpha = 1f
showingPopup = true showingPopup = true
animateViewIn(popupView) popupView
.animate()
.scaleX(1f)
.scaleY(1f)
.setInterpolator(popupEnterInterpolator)
.setDuration(popupEnterDuration.toLong())
.start()
} }
private fun hidePopup() { private fun hidePopup() {
@ -444,22 +505,13 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
showingPopup = false showingPopup = false
animateViewOut(popupView) popupView
}
private fun animateViewIn(view: View) {
view
.animate()
.alpha(1f)
.setDuration(context.getInteger(R.integer.anim_fade_enter_duration).toLong())
.start()
}
private fun animateViewOut(view: View) {
view
.animate() .animate()
.alpha(0f) .alpha(0f)
.setDuration(context.getInteger(R.integer.anim_fade_exit_duration).toLong()) .scaleX(0.75f)
.scaleY(0.75f)
.setInterpolator(popupExitInterpolator)
.setDuration(popupExitDuration.toLong())
.start() .start()
} }

View file

@ -21,7 +21,6 @@ package org.oxycblt.auxio.playback.service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.media.audiofx.AudioEffect import android.media.audiofx.AudioEffect
import android.os.Bundle
import androidx.media3.common.AudioAttributes import androidx.media3.common.AudioAttributes
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem

View file

@ -21,11 +21,11 @@ package org.oxycblt.auxio.playback.ui
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.animation.AnimationUtils import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.google.android.material.R as MR
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import org.oxycblt.auxio.R import com.google.android.material.motion.MotionUtils
import org.oxycblt.auxio.ui.RippleFixMaterialButton import org.oxycblt.auxio.ui.RippleFixMaterialButton
import org.oxycblt.auxio.util.getInteger
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
/** /**
@ -48,6 +48,13 @@ class AnimatedMaterialButton : RippleFixMaterialButton {
private var currentCornerRadiusRatio = 0f private var currentCornerRadiusRatio = 0f
private var animator: ValueAnimator? = null private var animator: ValueAnimator? = null
private val matInterpolator =
MotionUtils.resolveThemeInterpolator(
context, MR.attr.motionEasingStandardInterpolator, FastOutSlowInInterpolator())
private val matDuration =
MotionUtils.resolveThemeDuration(context, MR.attr.motionDurationMedium2, 300)
override fun setActivated(activated: Boolean) { override fun setActivated(activated: Boolean) {
super.setActivated(activated) super.setActivated(activated)
@ -64,10 +71,8 @@ class AnimatedMaterialButton : RippleFixMaterialButton {
animator?.cancel() animator?.cancel()
animator = animator =
ValueAnimator.ofFloat(currentCornerRadiusRatio, targetRadius).apply { ValueAnimator.ofFloat(currentCornerRadiusRatio, targetRadius).apply {
duration = context.getInteger(R.integer.anim_fade_enter_duration).toLong() duration = matDuration.toLong()
interpolator = interpolator = matInterpolator
AnimationUtils.loadInterpolator(
context, android.R.interpolator.fast_out_slow_in)
addUpdateListener { updateCornerRadiusRatio(animatedValue as Float) } addUpdateListener { updateCornerRadiusRatio(animatedValue as Float) }
start() start()
} }