From 00b7e0cac3007c86947c746493a621bcb2ab84c5 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Sun, 5 Sep 2021 20:22:40 -0600 Subject: [PATCH] ui: further apply elevation overlays Apply elevation overlays to CompactPlaybackFragment and dragged queue items. This makes elevation more noticable on dark mode. --- .../java/org/oxycblt/auxio/MainFragment.kt | 17 +++++-------- .../auxio/playback/queue/QueueAdapter.kt | 5 ++++ .../auxio/playback/queue/QueueDragCallback.kt | 16 ++++++------ .../auxio/playback/queue/QueueFragment.kt | 6 +---- .../java/org/oxycblt/auxio/util/ViewUtil.kt | 25 ++++++++++++++++--- app/src/main/res/layout/fragment_main.xml | 5 ++-- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 46f30259b..0c97359d5 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -27,9 +27,9 @@ import androidx.core.view.updatePadding import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import org.oxycblt.auxio.databinding.FragmentMainBinding -import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.applyEdge +import org.oxycblt.auxio.util.applyMaterialDrawable import org.oxycblt.auxio.util.logD /** @@ -51,29 +51,24 @@ class MainFragment : Fragment() { binding.lifecycleOwner = viewLifecycleOwner binding.applyEdge { bars -> - binding.root.updatePadding(bottom = bars.bottom) + binding.mainPlayback.updatePadding(bottom = bars.bottom) } + binding.mainPlayback.applyMaterialDrawable() + // --- VIEWMODEL SETUP --- playbackModel.setupPlayback(requireContext()) // Change CompactPlaybackFragment's visibility here so that an animation occurs. - handleCompactPlaybackVisibility(binding, playbackModel.song.value) + binding.mainPlayback.isVisible = playbackModel.song.value != null playbackModel.song.observe(viewLifecycleOwner) { song -> - handleCompactPlaybackVisibility(binding, song) + binding.mainPlayback.isVisible = song != null } logD("Fragment Created.") return binding.root } - - /** - * Handle the visibility of CompactPlaybackFragment. Done here so that there's a nice animation. - */ - private fun handleCompactPlaybackVisibility(binding: FragmentMainBinding, song: Song?) { - binding.mainPlayback.isVisible = song != null - } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index 567cb1bb4..dca6ffe6a 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -35,6 +35,7 @@ import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.BaseViewHolder import org.oxycblt.auxio.ui.DiffCallback import org.oxycblt.auxio.ui.HeaderViewHolder +import org.oxycblt.auxio.util.applyMaterialDrawable import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.logE @@ -158,6 +159,10 @@ class QueueAdapter( private val binding: ItemQueueSongBinding, ) : BaseViewHolder(binding) { + init { + binding.root.applyMaterialDrawable() + } + @SuppressLint("ClickableViewAccessibility") override fun onBind(data: Song) { binding.song = data diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt index b4cffad72..38f0732f5 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt @@ -20,10 +20,9 @@ package org.oxycblt.auxio.playback.queue import android.graphics.Canvas import android.view.animation.AccelerateDecelerateInterpolator -import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.shape.MaterialShapeDrawable import org.oxycblt.auxio.R import org.oxycblt.auxio.playback.PlaybackViewModel import kotlin.math.abs @@ -36,13 +35,8 @@ import kotlin.math.sign * of the UI magic that makes up the queue UI. * @author OxygenCobalt */ -class QueueDragCallback( - private val playbackModel: PlaybackViewModel, - private val coordinator: CoordinatorLayout, - private val appBar: AppBarLayout -) : ItemTouchHelper.Callback() { +class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouchHelper.Callback() { private lateinit var queueAdapter: QueueAdapter - private val tConsumed = IntArray(2) private var shouldLift = true override fun getMovementFlags( @@ -100,9 +94,12 @@ class QueueDragCallback( val view = viewHolder.itemView if (shouldLift && isCurrentlyActive && actionState == ItemTouchHelper.ACTION_STATE_DRAG) { + val bg = view.background as MaterialShapeDrawable + view.animate() .translationZ(view.resources.getDimension(R.dimen.elevation_small)) .setDuration(100) + .setUpdateListener { bg.elevation = view.translationZ } .setInterpolator(AccelerateDecelerateInterpolator()) .start() @@ -118,9 +115,12 @@ class QueueDragCallback( val view = viewHolder.itemView if (view.translationZ != 0.0f) { + val bg = view.background as MaterialShapeDrawable + view.animate() .translationZ(0.0f) .setDuration(100) + .setUpdateListener { bg.elevation = view.translationZ } .setInterpolator(AccelerateDecelerateInterpolator()) .start() } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index d7f622034..f810e1266 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -50,11 +50,7 @@ class QueueFragment : Fragment() { ): View { val binding = FragmentQueueBinding.inflate(inflater) - val callback = QueueDragCallback( - playbackModel, - binding.queueCoordinator, - binding.queueAppbar - ) + val callback = QueueDragCallback(playbackModel) val helper = ItemTouchHelper(callback) val queueAdapter = QueueAdapter(helper, playbackModel) diff --git a/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt index cbdbe4545..6087f8f06 100644 --- a/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/ViewUtil.kt @@ -22,6 +22,7 @@ import android.content.Context import android.content.res.ColorStateList import android.content.res.Resources import android.graphics.Rect +import android.graphics.drawable.ColorDrawable import android.os.Build import android.util.TypedValue import android.view.View @@ -35,8 +36,23 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.shape.MaterialShapeDrawable import org.oxycblt.auxio.R +/** + * Apply a [MaterialShapeDrawable] to this view, automatically initializing the elevation overlay + * and setting the fill color. This assumes that the background is a [ColorDrawable] and will + * crash if not. + */ +fun View.applyMaterialDrawable() { + check(background is ColorDrawable) { "Background was not defined as a solid color" } + + background = MaterialShapeDrawable.createWithElevationOverlay(context).apply { + elevation = this@applyMaterialDrawable.elevation + fillColor = ColorStateList.valueOf((background as ColorDrawable).color) + } +} + /** * Apply the recommended spans for a [RecyclerView]. * @@ -65,6 +81,11 @@ fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) { } } +/** + * Returns whether a recyclerview can scroll. + */ +fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height + /** * Disable an image button. * TODO: Replace this fragile function with something else. @@ -75,10 +96,6 @@ fun ImageButton.disable() { isEnabled = false } } -/** - * Returns whether a recyclerview can scroll. - */ -fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height /** * Resolve a color. diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 4435a94a6..3c76cb158 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -25,9 +25,10 @@ android:name="org.oxycblt.auxio.playback.CompactPlaybackFragment" android:layout_width="match_parent" android:layout_height="wrap_content" - android:elevation="@dimen/elevation_normal" - android:clipToPadding="true" android:background="?attr/colorSurface" + android:clipToPadding="true" + android:elevation="@dimen/elevation_normal" tools:layout="@layout/fragment_compact_playback" /> + \ No newline at end of file