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:
parent
df49e2765f
commit
4f4f6654c0
10 changed files with 150 additions and 101 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
104
app/src/main/res/layout/widget_medium.xml
Normal file
104
app/src/main/res/layout/widget_medium.xml
Normal 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>
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue