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) {
|
private fun RemoteViews.applyMeta(context: Context, state: WidgetState) {
|
||||||
setTextViewText(R.id.widget_song, state.song.name)
|
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) {
|
if (state.albumArt != null) {
|
||||||
setImageViewBitmap(R.id.widget_cover, state.albumArt)
|
setImageViewBitmap(R.id.widget_cover, state.albumArt)
|
||||||
|
@ -92,15 +92,15 @@ fun createDefaultWidget(context: Context): RemoteViews {
|
||||||
return createViews(context, R.layout.widget_default)
|
return createViews(context, R.layout.widget_default)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCompactWidget(context: Context, state: WidgetState): RemoteViews {
|
fun createTinyWidget(context: Context, state: WidgetState): RemoteViews {
|
||||||
val views = createViews(context, R.layout.widget_compact)
|
val views = createViews(context, R.layout.widget_tiny)
|
||||||
views.applyMeta(context, state)
|
views.applyMeta(context, state)
|
||||||
views.applyControls(context, state)
|
views.applyControls(context, state)
|
||||||
return views
|
return views
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createMinimalWidget(context: Context, state: WidgetState): RemoteViews {
|
fun createWideWidget(context: Context, state: WidgetState): RemoteViews {
|
||||||
val views = createViews(context, R.layout.widget_minimal)
|
val views = createViews(context, R.layout.widget_wide)
|
||||||
views.applyMeta(context, state)
|
views.applyMeta(context, state)
|
||||||
views.applyControls(context, state)
|
views.applyControls(context, state)
|
||||||
return views
|
return views
|
||||||
|
@ -113,8 +113,15 @@ fun createSmallWidget(context: Context, state: WidgetState): RemoteViews {
|
||||||
return views
|
return views
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFullWidget(context: Context, state: WidgetState): RemoteViews {
|
fun createMediumWidget(context: Context, state: WidgetState): RemoteViews {
|
||||||
val views = createViews(context, R.layout.widget_full)
|
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.applyMeta(context, state)
|
||||||
views.applyControls(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
|
* packing what could be considered multiple widgets into a single responsive widget. All types
|
||||||
* are listed below:
|
* are listed below:
|
||||||
*
|
*
|
||||||
* - Full: Large widgets will show cover art and all controls
|
* - Large widgets will show cover art and all controls
|
||||||
* - Small: Tall and thin widgets will show cover art and three controls
|
* - 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
|
* - 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
|
* - 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
|
* 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.
|
* 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.
|
// Map each widget form to the cells where it would look at least okay.
|
||||||
val views = mapOf(
|
val views = mapOf(
|
||||||
SizeF(180f, 152f) to createMinimalWidget(context, state),
|
SizeF(180f, 100f) to createTinyWidget(context, state),
|
||||||
SizeF(272f, 152f) to createCompactWidget(context, state),
|
SizeF(180f, 152f) to createSmallWidget(context, state),
|
||||||
SizeF(180f, 270f) to createSmallWidget(context, state),
|
SizeF(272f, 152f) to createWideWidget(context, state),
|
||||||
SizeF(272f, 270f) to createFullWidget(context, state)
|
SizeF(180f, 270f) to createMediumWidget(context, state),
|
||||||
|
SizeF(272f, 270f) to createLargeWidget(context, state)
|
||||||
)
|
)
|
||||||
|
|
||||||
appWidgetManager.applyViewsCompat(context, views)
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout 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:id="@android:id/background"
|
||||||
android:background="?attr/colorSurface"
|
|
||||||
android:theme="@style/Theme.Widget"
|
|
||||||
android:layout_width="match_parent"
|
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">
|
||||||
|
|
||||||
<!--
|
<android.widget.LinearLayout style="@style/Widget.Auxio.AppWidget.Panel">
|
||||||
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.widget.TextView
|
||||||
android:id="@+id/widget_song"
|
android:id="@+id/widget_song"
|
||||||
|
@ -66,8 +27,7 @@
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/spacing_medium"
|
android:layout_marginTop="@dimen/spacing_medium">
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<android.widget.ImageButton
|
<android.widget.ImageButton
|
||||||
android:id="@+id/widget_skip_prev"
|
android:id="@+id/widget_skip_prev"
|
||||||
|
@ -99,6 +59,5 @@
|
||||||
</android.widget.LinearLayout>
|
</android.widget.LinearLayout>
|
||||||
|
|
||||||
</android.widget.LinearLayout>
|
</android.widget.LinearLayout>
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface"
|
||||||
android:theme="@style/Theme.Widget">
|
android:theme="@style/Theme.Widget">
|
||||||
|
|
||||||
<android.widget.LinearLayout style="@style/Widget.Auxio.AppWidget.Panel">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
style="@style/Widget.Auxio.AppWidget.Panel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -24,9 +25,9 @@
|
||||||
android:src="@drawable/ic_song" />
|
android:src="@drawable/ic_song" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.widget.TextView
|
<android.widget.TextView
|
||||||
|
@ -44,42 +45,18 @@
|
||||||
android:text="@string/def_widget_artist" />
|
android:text="@string/def_widget_artist" />
|
||||||
|
|
||||||
</LinearLayout>
|
</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.widget.ImageButton
|
||||||
android:id="@+id/widget_play_pause"
|
android:id="@+id/widget_play_pause"
|
||||||
style="@style/Widget.Auxio.Button.AppWidget"
|
style="@style/Widget.Auxio.Button.AppWidget"
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="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: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>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.widget.LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -43,7 +43,7 @@
|
||||||
<dimen name="popup_padding_end">28dp</dimen>
|
<dimen name="popup_padding_end">28dp</dimen>
|
||||||
|
|
||||||
<dimen name="widget_width_min">176dp</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_width_def">@dimen/widget_width_min</dimen>
|
||||||
<dimen name="widget_height_def">180dp</dimen>
|
<dimen name="widget_height_def">180dp</dimen>
|
||||||
</resources>
|
</resources>
|
|
@ -1,10 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:description="@string/info_widget_desc"
|
android:description="@string/info_widget_desc"
|
||||||
android:initialLayout="@layout/widget_minimal"
|
android:initialLayout="@layout/widget_medium"
|
||||||
android:minResizeWidth="@dimen/widget_width_min"
|
android:minResizeWidth="@dimen/widget_width_min"
|
||||||
android:minResizeHeight="@dimen/widget_height_min"
|
android:minResizeHeight="@dimen/widget_height_min"
|
||||||
android:previewLayout="@layout/widget_minimal"
|
android:previewLayout="@layout/widget_medium"
|
||||||
android:previewImage="@drawable/ui_widget_preview"
|
android:previewImage="@drawable/ui_widget_preview"
|
||||||
android:resizeMode="horizontal|vertical"
|
android:resizeMode="horizontal|vertical"
|
||||||
android:minWidth="@dimen/widget_width_def"
|
android:minWidth="@dimen/widget_width_def"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
<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:minWidth="@dimen/widget_width_min"
|
||||||
android:minHeight="@dimen/widget_height_min"
|
android:minHeight="@dimen/widget_height_min"
|
||||||
android:minResizeWidth="@dimen/widget_width_def"
|
android:minResizeWidth="@dimen/widget_width_def"
|
||||||
|
|
Loading…
Reference in a new issue