widgets: add widget layout preview

Add a layout preview to the Android 12 widget metadata. I'm holding off
on implementing a drawable until the widgets are completely finalized.
This commit is contained in:
OxygenCobalt 2021-08-03 10:33:07 -06:00
parent 8551e90884
commit 49db7e0741
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
11 changed files with 54 additions and 29 deletions

View file

@ -369,6 +369,9 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
onLoopUpdate(playbackManager.loopMode)
onSongUpdate(playbackManager.song)
onSeek(playbackManager.position)
// Notify other classes that rely on this service to also update.
widgets.update()
}
/**
@ -495,9 +498,11 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
}
}
BaseWidget.ACTION_WIDGET_UPDATE -> widgets.initWidget(
intent.getIntExtra(BaseWidget.ACTION_WIDGET_UPDATE, -1)
)
BaseWidget.ACTION_WIDGET_UPDATE -> {
widgets.initWidget(
intent.getIntExtra(BaseWidget.KEY_WIDGET_TYPE, -1)
)
}
}
}

View file

@ -155,8 +155,8 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
val list = mutableListOf<Song>()
songs.groupBy { it.album }.entries.sortedWith(compareByDescending { it.key.year }).forEach { entry ->
list.addAll(entry.value.sortedWith(compareBy { it.track }))
}
list.addAll(entry.value.sortedWith(compareBy { it.track }))
}
list
}

View file

@ -45,8 +45,6 @@ abstract class BaseWidget : AppWidgetProvider() {
* Update the widget based on the playback state.
*/
fun update(context: Context, playbackManager: PlaybackStateManager) {
logD("Dispatching playback state update")
val manager = AppWidgetManager.getInstance(context)
// View updates are often async due to image loading, so only push the views
@ -57,10 +55,10 @@ abstract class BaseWidget : AppWidgetProvider() {
}
/*
* Stop this widget, reverting it to its default state.
* Revert this widget to its default view
*/
fun stop(context: Context) {
logD("Stopping widget")
fun reset(context: Context) {
logD("Resetting widget")
val manager = AppWidgetManager.getInstance(context)
manager.applyViews(context, defaultViews(context))
@ -71,10 +69,10 @@ abstract class BaseWidget : AppWidgetProvider() {
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
appWidgetManager.applyViews(context, defaultViews(context))
logD("Sending update intent to PlaybackService")
appWidgetManager.applyViews(context, defaultViews(context))
val intent = Intent(ACTION_WIDGET_UPDATE)
.putExtra(KEY_WIDGET_TYPE, type)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)

View file

@ -51,7 +51,7 @@ class MinimalWidgetProvider : BaseWidget() {
val song = playbackManager.song
if (song != null) {
logD("updating view to ${song.name}")
logD("Updating view to ${song.name}")
val views = createViews(context, R.layout.widget_minimal)
@ -88,6 +88,8 @@ class MinimalWidgetProvider : BaseWidget() {
onDone(views)
}
} else {
logD("No song playing, reverting to default view")
onDone(defaultViews(context))
}
}

View file

@ -1,33 +1,44 @@
package org.oxycblt.auxio.widgets
import android.content.Context
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.state.PlaybackStateManager
class WidgetController(private val context: Context) : PlaybackStateManager.Callback {
private val manager = PlaybackStateManager.getInstance()
private val playbackManager = PlaybackStateManager.getInstance()
private val minimal = MinimalWidgetProvider()
init {
manager.addCallback(this)
playbackManager.addCallback(this)
}
fun initWidget(type: Int) {
logD("Updating new widget $type")
when (type) {
MinimalWidgetProvider.TYPE -> minimal.update(context, manager)
MinimalWidgetProvider.TYPE -> minimal.update(context, playbackManager)
}
}
fun update() {
logD("Updating all widgets")
minimal.update(context, playbackManager)
}
fun release() {
minimal.stop(context)
manager.removeCallback(this)
logD("Resetting widgets")
minimal.reset(context)
playbackManager.removeCallback(this)
}
override fun onSongUpdate(song: Song?) {
minimal.update(context, manager)
minimal.update(context, playbackManager)
}
override fun onPlayingUpdate(isPlaying: Boolean) {
minimal.update(context, manager)
minimal.update(context, playbackManager)
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="@android:dimen/system_app_widget_inner_radius" />
</shape>

View file

@ -15,13 +15,13 @@
android:background="?attr/colorSurface"
android:scaleType="centerCrop"
tools:ignore="contentDescription"
tools:src="@drawable/ic_song" />
android:src="@drawable/ic_song" />
<android.widget.LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/colorBackground"
android:background="?attr/colorSurface"
android:orientation="vertical"
android:padding="@dimen/spacing_medium">
@ -35,7 +35,7 @@
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold"
tools:text="Song Name" />
android:text="@string/placeholder_widget_song" />
<android.widget.TextView
android:id="@+id/widget_artist"
@ -46,13 +46,12 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textColor="?android:attr/textColorSecondary"
tools:text="Artist Name" />
android:text="@string/placeholder_widget_artist" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginTop="@dimen/spacing_small"
android:orientation="horizontal">
<ImageButton

View file

@ -3,6 +3,7 @@
android:id="@android:id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:theme="@style/Theme.Widget">
<android.widget.ImageView

View file

@ -52,9 +52,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
android:gravity="center"
android:orientation="horizontal">
android:layout_marginTop="@dimen/spacing_small">
<!--
Can't use a normal unbounded ripple here since it causes a weird bug

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation">
<!-- Info namespace | App labels -->
<string name="info_app_desc">A simple, rational music player for android.</string>
<string name="info_channel_name">Music Playback</string>
@ -137,6 +138,8 @@
<string name="placeholder_album">Unknown Album</string>
<string name="placeholder_no_date">No Date</string>
<string name="placeholder_playback">No music playing</string>
<string name="placeholder_widget_song">Song Name</string>
<string name="placeholder_widget_artist">Artist Name</string>
<!-- Color Label namespace | Accent names -->
<string name="color_label_red">Red</string>

View file

@ -5,6 +5,7 @@
android:targetCellHeight="2"
android:minResizeWidth="110dp"
android:minResizeHeight="110dp"
android:previewLayout="@layout/widget_minimal"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen">