ui: clean up colors
Further clean up coloring, adding new selectors to cut down on resource duplication and to simplify logic in general.
This commit is contained in:
parent
34367b3bae
commit
0fc8f1cd02
18 changed files with 44 additions and 83 deletions
|
@ -29,15 +29,12 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.accent.Accent
|
||||
import org.oxycblt.auxio.databinding.FragmentPlaybackBinding
|
||||
import org.oxycblt.auxio.detail.DetailViewModel
|
||||
import org.oxycblt.auxio.playback.state.LoopMode
|
||||
import org.oxycblt.auxio.ui.memberBinding
|
||||
import org.oxycblt.auxio.util.applyEdge
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.resolveDrawable
|
||||
import org.oxycblt.auxio.util.resolveStateList
|
||||
|
||||
/**
|
||||
* A [Fragment] that displays more information about the song, along with more media controls.
|
||||
|
@ -48,7 +45,7 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private val binding by memberBinding(FragmentPlaybackBinding::inflate) {
|
||||
playbackSong.isSelected = false
|
||||
playbackSong.isSelected = false // Clear marquee to prevent a memory leak
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -56,14 +53,6 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val normalTextColor = binding.playbackDurationCurrent.currentTextColor
|
||||
val accentColor = Accent.get().getStateList(requireContext())
|
||||
val controlColor = R.color.control.resolveStateList(requireContext())
|
||||
|
||||
// Can't set the tint of a MenuItem below Android 8, so use icons instead.
|
||||
val iconQueueActive = R.drawable.ic_queue.resolveDrawable(requireContext())
|
||||
val iconQueueInactive = R.drawable.ic_queue_inactive.resolveDrawable(requireContext())
|
||||
|
||||
val queueItem: MenuItem
|
||||
|
||||
// --- UI SETUP ---
|
||||
|
@ -102,6 +91,7 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
binding.playbackSeekBar.setOnSeekBarChangeListener(this)
|
||||
|
||||
// --- VIEWMODEL SETUP --
|
||||
|
||||
playbackModel.song.observe(viewLifecycleOwner) { song ->
|
||||
if (song != null) {
|
||||
logD("Updating song display to ${song.name}.")
|
||||
|
@ -120,32 +110,17 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
}
|
||||
|
||||
playbackModel.loopMode.observe(viewLifecycleOwner) { loopMode ->
|
||||
when (loopMode) {
|
||||
LoopMode.NONE -> {
|
||||
binding.playbackLoop.imageTintList = controlColor
|
||||
binding.playbackLoop.setImageResource(R.drawable.ic_loop)
|
||||
val resId = when (loopMode) {
|
||||
LoopMode.NONE, null -> R.drawable.ic_loop
|
||||
LoopMode.ALL -> R.drawable.ic_loop_on
|
||||
LoopMode.TRACK -> R.drawable.ic_loop_one
|
||||
}
|
||||
|
||||
LoopMode.ALL -> {
|
||||
binding.playbackLoop.imageTintList = accentColor
|
||||
binding.playbackLoop.setImageResource(R.drawable.ic_loop)
|
||||
}
|
||||
|
||||
LoopMode.TRACK -> {
|
||||
binding.playbackLoop.imageTintList = accentColor
|
||||
binding.playbackLoop.setImageResource(R.drawable.ic_loop_one)
|
||||
}
|
||||
|
||||
else -> return@observe
|
||||
}
|
||||
binding.playbackLoop.setImageResource(resId)
|
||||
}
|
||||
|
||||
playbackModel.isSeeking.observe(viewLifecycleOwner) { isSeeking ->
|
||||
if (isSeeking) {
|
||||
binding.playbackDurationCurrent.setTextColor(accentColor)
|
||||
} else {
|
||||
binding.playbackDurationCurrent.setTextColor(normalTextColor)
|
||||
}
|
||||
binding.playbackDurationCurrent.isActivated = isSeeking
|
||||
}
|
||||
|
||||
playbackModel.positionAsProgress.observe(viewLifecycleOwner) { pos ->
|
||||
|
@ -155,27 +130,11 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
}
|
||||
|
||||
playbackModel.nextItemsInQueue.observe(viewLifecycleOwner) { nextQueue ->
|
||||
val userQueue = playbackModel.userQueue.value!!
|
||||
|
||||
if (userQueue.isEmpty() && nextQueue.isEmpty()) {
|
||||
queueItem.icon = iconQueueInactive
|
||||
queueItem.isEnabled = false
|
||||
} else {
|
||||
queueItem.icon = iconQueueActive
|
||||
queueItem.isEnabled = true
|
||||
}
|
||||
updateQueueIcon(queueItem)
|
||||
}
|
||||
|
||||
playbackModel.userQueue.observe(viewLifecycleOwner) { userQueue ->
|
||||
val nextQueue = playbackModel.nextItemsInQueue.value!!
|
||||
|
||||
if (userQueue.isEmpty() && nextQueue.isEmpty()) {
|
||||
queueItem.icon = iconQueueInactive
|
||||
queueItem.isEnabled = false
|
||||
} else {
|
||||
queueItem.icon = iconQueueActive
|
||||
queueItem.isEnabled = true
|
||||
}
|
||||
updateQueueIcon(queueItem)
|
||||
}
|
||||
|
||||
playbackModel.isPlaying.observe(viewLifecycleOwner) { isPlaying ->
|
||||
|
@ -193,6 +152,15 @@ class PlaybackFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
|
|||
return binding.root
|
||||
}
|
||||
|
||||
private fun updateQueueIcon(queueItem: MenuItem) {
|
||||
val userQueue = playbackModel.userQueue.value!!
|
||||
val nextQueue = playbackModel.nextItemsInQueue.value!!
|
||||
|
||||
// The queue icon uses a selector that will automatically tint the icon as active or
|
||||
// inactive. We just need to set the flag.
|
||||
queueItem.isEnabled = !(userQueue.isEmpty() && nextQueue.isEmpty())
|
||||
}
|
||||
|
||||
// --- SEEK CALLBACKS ---
|
||||
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||
|
|
|
@ -75,7 +75,7 @@ fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) {
|
|||
*/
|
||||
fun ImageButton.disable() {
|
||||
if (isEnabled) {
|
||||
imageTintList = R.color.inactive.resolveStateList(context)
|
||||
imageTintList = ContextCompat.getColorStateList(context, R.color.overlay_disabled)
|
||||
isEnabled = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ fun createFullWidget(context: Context, state: WidgetState): RemoteViews {
|
|||
|
||||
val loopRes = when (state.loopMode) {
|
||||
LoopMode.NONE -> R.drawable.ic_loop
|
||||
LoopMode.ALL -> R.drawable.ic_loop_tinted
|
||||
LoopMode.ALL -> R.drawable.ic_loop_on
|
||||
LoopMode.TRACK -> R.drawable.ic_loop_one
|
||||
}
|
||||
|
||||
|
|
5
app/src/main/res/color/overlay_disabled.xml
Normal file
5
app/src/main/res/color/overlay_disabled.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?attr/colorOnSurface" android:alpha="0.24" android:state_enabled="false" />
|
||||
<item android:color="?attr/colorControlNormal" />
|
||||
</selector>
|
|
@ -2,5 +2,5 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?attr/colorAccent"
|
||||
android:state_activated="true" />
|
||||
<item android:color="?android:attr/textColorTertiary" />
|
||||
<item android:color="?android:attr/textColorSecondary" />
|
||||
</selector>
|
|
@ -2,7 +2,7 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:tint="@color/overlay_disabled"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="@color/inactive"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18C16.69 14.07 16.35 14 16 14c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z" />
|
||||
</vector>
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?attr/colorControlHighlight">
|
||||
android:color="@color/mtrl_btn_ripple_color">
|
||||
<item>
|
||||
<shape android:shape="oval"
|
||||
android:tint="@color/sel_accent_active">
|
||||
android:tint="@color/sel_accented">
|
||||
<solid android:color="@android:color/white" />
|
||||
</shape>
|
||||
</item>
|
||||
|
|
|
@ -116,6 +116,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:text="@{playbackModel.formattedPosition}"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
|
@ -183,7 +184,7 @@
|
|||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:tint="@color/sel_accent_active"
|
||||
app:tint="@color/sel_accented"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song_duration"
|
||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" />
|
||||
|
|
|
@ -117,6 +117,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:text="@{playbackModel.formattedPosition}"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_cover"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar"
|
||||
|
@ -184,7 +185,7 @@
|
|||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:tint="@color/sel_accent_active"
|
||||
app:tint="@color/sel_accented"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" />
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
android:layout_marginStart="@dimen/spacing_mid_huge"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:text="@{playbackModel.formattedPosition}"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="11:38" />
|
||||
|
@ -171,7 +172,7 @@
|
|||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:tint="@color/sel_accent_active"
|
||||
app:tint="@color/sel_accented"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
app:layout_constraintStart_toEndOf="@+id/playback_skip_next"
|
||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" />
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
android:layout_marginStart="@dimen/spacing_mid_large"
|
||||
android:layout_marginBottom="@dimen/spacing_medium"
|
||||
android:text="@{playbackModel.formattedPosition}"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="11:38" />
|
||||
|
@ -167,7 +168,7 @@
|
|||
android:contentDescription="@string/desc_shuffle"
|
||||
android:onClick="@{() -> playbackModel.invertShuffleStatus()}"
|
||||
android:src="@drawable/ic_shuffle"
|
||||
app:tint="@color/sel_accent_active"
|
||||
app:tint="@color/sel_accented"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
|
||||
app:layout_constraintEnd_toEndOf="@+id/playback_song_duration"
|
||||
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" />
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
android:text="@{String.valueOf(song.track)}"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:textColor="@color/sel_accented_track"
|
||||
android:textColor="@color/sel_accented_secondary"
|
||||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="surface">@color/surface_night</color>
|
||||
<color name="inactive">#404040</color>
|
||||
<color name="surface">#202124</color>
|
||||
<color name="control">#ffffff</color>
|
||||
<color name="nav_bar">#01151515</color>
|
||||
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="surface_day">#fafafa</color>
|
||||
<color name="surface_night">#202124</color>
|
||||
<color name="surface">#fafafa</color>
|
||||
<color name="surface_black">@android:color/black</color>
|
||||
|
||||
<color name="surface">@color/surface_day</color>
|
||||
<color name="control">#202020</color>
|
||||
<color name="inactive">#c4c4c4</color>
|
||||
<color name="nav_bar">#01fafafa</color>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<style name="Widget.ProgressBar.Compact" parent="@style/Widget.AppCompat.ProgressBar.Horizontal">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">@dimen/size_stroke_large</item>
|
||||
<item name="android:progressBackgroundTint">?attr/colorControlNormal</item>
|
||||
<item name="android:progressBackgroundTint">?attr/colorAccent</item>
|
||||
<item name="android:progressTint">?attr/colorAccent</item>
|
||||
</style>
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
|||
<item name="android:focusable">true</item>
|
||||
<item name="android:paddingStart">@dimen/spacing_mid_large</item>
|
||||
<item name="android:paddingEnd">@dimen/spacing_mid_large</item>
|
||||
<item name="android:progressBackgroundTint">?android:attr/colorControlNormal</item>
|
||||
<item name="android:progressBackgroundTint">?attr/colorAccent</item>
|
||||
<item name="android:progressTint">?attr/colorAccent</item>
|
||||
<item name="android:splitTrack">false</item>
|
||||
<item name="android:thumbOffset">@dimen/offset_thumb</item>
|
||||
|
|
Loading…
Reference in a new issue