ui: further apply elevation overlays
Apply elevation overlays to CompactPlaybackFragment and dragged queue items. This makes elevation more noticable on dark mode.
This commit is contained in:
parent
0433abc5cb
commit
00b7e0cac3
6 changed files with 44 additions and 30 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Song>(binding) {
|
||||
|
||||
init {
|
||||
binding.root.applyMaterialDrawable()
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onBind(data: Song) {
|
||||
binding.song = data
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
Loading…
Reference in a new issue