widgets: re-add 2x2 widgets

Re-add 2x2 widgets. They were originally removed due to strange layouts
in landscape mode, but that has now been fixed with a new "tiny" layout
meant for that specific edge case. Also rename the widget forms to more
sensible names and make the small (previously minimal) widget be
text-only again.
This commit is contained in:
OxygenCobalt 2021-10-28 19:46:00 -06:00
parent df49e2765f
commit 4f4f6654c0
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
10 changed files with 150 additions and 101 deletions

View file

@ -43,7 +43,7 @@ private fun createViews(
private fun RemoteViews.applyMeta(context: Context, state: WidgetState) {
setTextViewText(R.id.widget_song, state.song.name)
setTextViewText(R.id.widget_artist, state.song.album.artist.name)
setTextViewText(R.id.widget_artist, state.song.album.artist.resolvedName)
if (state.albumArt != null) {
setImageViewBitmap(R.id.widget_cover, state.albumArt)
@ -92,15 +92,15 @@ fun createDefaultWidget(context: Context): RemoteViews {
return createViews(context, R.layout.widget_default)
}
fun createCompactWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_compact)
fun createTinyWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_tiny)
views.applyMeta(context, state)
views.applyControls(context, state)
return views
}
fun createMinimalWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_minimal)
fun createWideWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_wide)
views.applyMeta(context, state)
views.applyControls(context, state)
return views
@ -113,8 +113,15 @@ fun createSmallWidget(context: Context, state: WidgetState): RemoteViews {
return views
}
fun createFullWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_full)
fun createMediumWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_medium)
views.applyMeta(context, state)
views.applyControls(context, state)
return views
}
fun createLargeWidget(context: Context, state: WidgetState): RemoteViews {
val views = createViews(context, R.layout.widget_large)
views.applyMeta(context, state)
views.applyControls(context, state)

View file

@ -46,10 +46,11 @@ import org.oxycblt.auxio.util.logD
* packing what could be considered multiple widgets into a single responsive widget. All types
* are listed below:
*
* - Full: Large widgets will show cover art and all controls
* - Small: Tall and thin widgets will show cover art and three controls
* - Compact: Wide and short widgets will show cover art and all controls in a compact manner
* - Minimal: Small widgets will only show cover art and three controls
* - Large widgets will show cover art and all controls
* - Tall and thin widgets will show cover art and three controls
* - Wide and short widgets will show cover art and all controls in a compact manner
* - Small widgets will only show text and three controls
* - Tiny widgets [e.g landscape mode] will show cover art, text, and a play/pause control.
*
* There are some minor problems with this implementation [notably UI jittering when the widget
* picks a new layout below Android 12], but this is tolerable. It may be improved in the future.
@ -80,10 +81,11 @@ class WidgetProvider : AppWidgetProvider() {
// Map each widget form to the cells where it would look at least okay.
val views = mapOf(
SizeF(180f, 152f) to createMinimalWidget(context, state),
SizeF(272f, 152f) to createCompactWidget(context, state),
SizeF(180f, 270f) to createSmallWidget(context, state),
SizeF(272f, 270f) to createFullWidget(context, state)
SizeF(180f, 100f) to createTinyWidget(context, state),
SizeF(180f, 152f) to createSmallWidget(context, state),
SizeF(272f, 152f) to createWideWidget(context, state),
SizeF(180f, 270f) to createMediumWidget(context, state),
SizeF(272f, 270f) to createLargeWidget(context, state)
)
appWidgetManager.applyViewsCompat(context, views)

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/background"
android:background="?attr/colorSurface"
android:theme="@style/Theme.Widget"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--
We can't use ConstraintLayout on widgets due to RemoteView limitations, but
for this widget form to work, we need to get the cover to preserve it's aspect
ratio. So, we use a fixed-size 1000x1000 drawable and then align the cover view
to that so that the bounds will scale properly.
This is easily one of the worst layout hacks I've done, but it seems to work.
-->
<ImageView
android:id="@+id/widget_aspect_ratio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_above="@+id/widget_panel"
android:src="@drawable/ui_widget_aspect_ratio"
android:visibility="invisible"
tools:ignore="ContentDescription" />
<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_song"
tools:ignore="ContentDescription" />
<android.widget.LinearLayout
android:id="@+id/widget_panel"
style="@style/Widget.Auxio.AppWidget.Panel"
android:layout_alignParentBottom="true"
android:layout_gravity="center">
<android.widget.TextView
android:id="@+id/widget_song"
style="@style/Widget.Auxio.TextView.Primary.AppWidget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/def_widget_song" />
<android.widget.TextView
android:id="@+id/widget_artist"
style="@style/Widget.Auxio.TextView.Secondary.AppWidget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/def_widget_artist" />
<android.widget.LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
android:orientation="horizontal">
<android.widget.ImageButton
android:id="@+id/widget_skip_prev"
style="@style/Widget.Auxio.Button.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.Button.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.Button.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>
</RelativeLayout>

View file

@ -1,53 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/background"
android:background="?attr/colorSurface"
android:theme="@style/Theme.Widget"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:gravity="center_vertical"
android:orientation="vertical"
android:theme="@style/Theme.Widget">
<!--
We can't use ConstraintLayout on widgets due to RemoteView limitations, but
for this widget form to work, we need to get the cover to preserve it's aspect
ratio. So, we use a fixed-size 1000x1000 drawable and then align the cover view
to that so that the bounds will scale properly.
This is easily one of the worst layout hacks I've done, but it seems to work.
-->
<ImageView
android:id="@+id/widget_aspect_ratio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:layout_marginTop="@dimen/spacing_medium"
android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_above="@+id/widget_panel"
android:src="@drawable/ui_widget_aspect_ratio"
android:visibility="invisible"
tools:ignore="ContentDescription" />
<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_song"
tools:ignore="ContentDescription" />
<android.widget.LinearLayout
android:id="@+id/widget_panel"
style="@style/Widget.Auxio.AppWidget.Panel"
android:layout_alignParentBottom="true"
android:layout_gravity="center">
<android.widget.LinearLayout style="@style/Widget.Auxio.AppWidget.Panel">
<android.widget.TextView
android:id="@+id/widget_song"
@ -66,8 +27,7 @@
<android.widget.LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
android:orientation="horizontal">
android:layout_marginTop="@dimen/spacing_medium">
<android.widget.ImageButton
android:id="@+id/widget_skip_prev"
@ -99,6 +59,5 @@
</android.widget.LinearLayout>
</android.widget.LinearLayout>
</RelativeLayout>
</LinearLayout>

View file

@ -8,11 +8,12 @@
android:background="?attr/colorSurface"
android:theme="@style/Theme.Widget">
<android.widget.LinearLayout style="@style/Widget.Auxio.AppWidget.Panel">
<LinearLayout
style="@style/Widget.Auxio.AppWidget.Panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
@ -24,9 +25,9 @@
android:src="@drawable/ic_song" />
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<android.widget.TextView
@ -44,42 +45,18 @@
android:text="@string/def_widget_artist" />
</LinearLayout>
</LinearLayout>
<android.widget.LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium">
<android.widget.ImageButton
android:id="@+id/widget_skip_prev"
style="@style/Widget.Auxio.Button.AppWidget"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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.Button.AppWidget"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="@dimen/size_btn_small"
android:minWidth="@dimen/size_btn_small"
android:contentDescription="@string/desc_play_pause"
android:src="@drawable/ic_play" />
android:src="@drawable/sel_playing_state" />
<android.widget.ImageButton
android:id="@+id/widget_skip_next"
style="@style/Widget.Auxio.Button.AppWidget"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/desc_skip_next"
android:src="@drawable/ic_skip_next" />
</android.widget.LinearLayout>
</android.widget.LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -43,7 +43,7 @@
<dimen name="popup_padding_end">28dp</dimen>
<dimen name="widget_width_min">176dp</dimen>
<dimen name="widget_height_min">180dp</dimen>
<dimen name="widget_height_min">110dp</dimen>
<dimen name="widget_width_def">@dimen/widget_width_min</dimen>
<dimen name="widget_height_def">180dp</dimen>
</resources>

View file

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/info_widget_desc"
android:initialLayout="@layout/widget_minimal"
android:initialLayout="@layout/widget_medium"
android:minResizeWidth="@dimen/widget_width_min"
android:minResizeHeight="@dimen/widget_height_min"
android:previewLayout="@layout/widget_minimal"
android:previewLayout="@layout/widget_medium"
android:previewImage="@drawable/ui_widget_preview"
android:resizeMode="horizontal|vertical"
android:minWidth="@dimen/widget_width_def"

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_minimal"
android:initialLayout="@layout/widget_medium"
android:minWidth="@dimen/widget_width_min"
android:minHeight="@dimen/widget_height_min"
android:minResizeWidth="@dimen/widget_width_def"