widgets: add thin widget

Rework the smallest widgets to have no textual metadata, alongside
adding a new widget size class.

Turns out the last tiny widget redesign made the controls far too
small. Instead, remove the textual metadata and make these widgets
more akin to the small and wide widgets. This also introduces a new
side class alongside that with more controls, again to make it
similar to the other size classes.
This commit is contained in:
OxygenCobalt 2022-05-24 17:10:23 -06:00
parent e1e032d254
commit b320f4b1bd
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 212 additions and 77 deletions

View file

@ -33,14 +33,21 @@ import org.oxycblt.auxio.util.newMainIntent
fun createDefaultWidget(context: Context) = createViews(context, R.layout.widget_default)
/**
* The tiny widget is for an edge-case situation where a widget falls under the size class of the
* small widget, either via landscape mode or exceptionally small screens.
* The tiny widget like a small or medium widget, but for landscape or exceptionally small screens.
*/
fun createTinyWidget(context: Context, state: WidgetComponent.WidgetState) =
createViews(context, R.layout.widget_tiny)
.applyMeta(context, state)
.applyCover(context, state)
.applyBasicControls(context, state)
/**
* The thin widget is like a wide or large widget, but for landscape or exceptionally small screens.
*/
fun createThinWidget(context: Context, state: WidgetComponent.WidgetState) =
createViews(context, R.layout.widget_thin)
.applyCover(context, state)
.applyFullControls(context, state)
/**
* The small widget is for 2x2 widgets and just shows the cover art and playback controls. This is
* generally because a Medium widget is too large for this widget size and a text-only widget is too

View file

@ -42,6 +42,8 @@ import org.oxycblt.auxio.util.unlikelyToBeNull
* changes. This is tolerable.
*
* For more specific details about these sub-widgets, see Forms.kt.
*
* @author OxygenCobalt
*/
class WidgetProvider : AppWidgetProvider() {
/*
@ -57,6 +59,7 @@ class WidgetProvider : AppWidgetProvider() {
val views =
mapOf(
SizeF(180f, 100f) to createTinyWidget(context, state),
SizeF(372f, 100f) to createThinWidget(context, state),
SizeF(180f, 152f) to createSmallWidget(context, state),
SizeF(272f, 152f) to createWideWidget(context, state),
SizeF(180f, 270f) to createMediumWidget(context, state),
@ -122,13 +125,6 @@ class WidgetProvider : AppWidgetProvider() {
val name = ComponentName(context, WidgetProvider::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
for (id in getAppWidgetIds(name)) {
val options = getAppWidgetOptions(id)
logD(
options.getParcelableArrayList<SizeF>(AppWidgetManager.OPTION_APPWIDGET_SIZES)
?: "no sizes")
}
// Widgets are automatically responsive on Android 12, no need to do anything.
updateAppWidget(name, RemoteViews(views))
} else {

View file

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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:orientation="horizontal"
android:baselineAligned="false">
<!--
Wrapping the 1:1 ImageView hack in a LinearLayout allows the view to measure greedily
without squishing the controls.
-->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<!--
See widget_small.xml for an explanation for the ImageView setup
-->
<android.widget.ImageView
android:id="@+id/widget_aspect_ratio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_medium"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/ui_remote_aspect_ratio"
android:visibility="invisible"
tools:ignore="ContentDescription" />
<android.widget.ImageView
android:id="@+id/widget_cover"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignStart="@id/widget_aspect_ratio"
android:layout_alignTop="@id/widget_aspect_ratio"
android:layout_alignEnd="@id/widget_aspect_ratio"
android:layout_alignBottom="@id/widget_aspect_ratio"
android:src="@drawable/ic_remote_default_cover"
tools:ignore="ContentDescription" />
</RelativeLayout>
<android.widget.LinearLayout
android:id="@+id/widget_panel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_gravity="center"
android:orientation="horizontal"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium">
<android.widget.ImageButton
android:id="@+id/widget_repeat"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_change_repeat"
android:src="@drawable/ic_repeat" />
<android.widget.ImageButton
android:id="@+id/widget_skip_prev"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_skip_prev"
android:src="@drawable/ic_skip_prev" />
<android.widget.ImageButton
android:id="@+id/widget_play_pause"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state" />
<android.widget.ImageButton
android:id="@+id/widget_skip_next"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_skip_next"
android:src="@drawable/ic_skip_next" />
<android.widget.ImageButton
android:id="@+id/widget_shuffle"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_shuffle"
android:src="@drawable/ic_shuffle_state" />
</android.widget.LinearLayout>
</LinearLayout>

View file

@ -1,83 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:gravity="center_vertical"
android:orientation="vertical"
android:theme="@style/Theme.Widget">
android:theme="@style/Theme.Widget"
android:orientation="horizontal"
android:baselineAligned="false">
<android.widget.LinearLayout
style="@style/Widget.Auxio.AppWidget.Panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!--
Wrapping the 1:1 ImageView hack in a LinearLayout allows the view to measure greedily
without squishing the controls.
-->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<!--
See widget_small.xml for an explanation for the ImageView setup
-->
<android.widget.ImageView
android:id="@+id/widget_aspect_ratio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_medium"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/ui_remote_aspect_ratio"
android:visibility="invisible"
tools:ignore="ContentDescription" />
<android.widget.ImageView
android:id="@+id/widget_cover"
android:layout_width="@dimen/size_cover_mid_large"
android:layout_height="@dimen/size_cover_mid_large"
android:layout_marginEnd="@dimen/spacing_medium"
android:contentDescription="@string/desc_no_cover"
android:scaleType="centerCrop"
android:src="@drawable/ic_remote_default_cover" />
<android.widget.LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignStart="@id/widget_aspect_ratio"
android:layout_alignTop="@id/widget_aspect_ratio"
android:layout_alignEnd="@id/widget_aspect_ratio"
android:layout_alignBottom="@id/widget_aspect_ratio"
android:src="@drawable/ic_remote_default_cover"
tools:ignore="ContentDescription" />
</RelativeLayout>
<android.widget.LinearLayout
android:id="@+id/widget_panel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_gravity="center"
android:orientation="horizontal"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginBottom="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium">
<android.widget.ImageButton
android:id="@+id/widget_skip_prev"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
android:contentDescription="@string/desc_skip_prev"
android:src="@drawable/ic_skip_prev" />
<android.widget.TextView
android:id="@+id/widget_song"
style="@style/Widget.Auxio.TextView.Primary.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/def_widget_song" />
<android.widget.ImageButton
android:id="@+id/widget_play_pause"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state" />
<android.widget.TextView
android:id="@+id/widget_artist"
style="@style/Widget.Auxio.TextView.Secondary.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/def_widget_artist" />
<android.widget.ImageButton
android:id="@+id/widget_skip_next"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_skip_next"
android:src="@drawable/ic_skip_next" />
<android.widget.LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small"
android:orientation="horizontal">
<android.widget.ImageButton
android:id="@+id/widget_skip_prev"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_skip_prev"
android:src="@drawable/ic_skip_prev" />
<android.widget.ImageButton
android:id="@+id/widget_play_pause"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/ic_play" />
<android.widget.ImageButton
android:id="@+id/widget_skip_next"
style="@style/Widget.Auxio.PlaybackButton.AppWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/desc_skip_next"
android:src="@drawable/ic_skip_next" />
</android.widget.LinearLayout>
</android.widget.LinearLayout>
</android.widget.LinearLayout>
</android.widget.LinearLayout>
</LinearLayout>