mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2025-10-29 03:36:21 +00:00
Add option to use cover image as widget background (#7924)
This commit is contained in:
parent
4b101583c5
commit
e3b587ae55
@ -901,6 +901,7 @@
|
||||
<string name="widget_settings">Widget settings</string>
|
||||
<string name="widget_create_button">Create widget</string>
|
||||
<string name="widget_opacity">Opacity</string>
|
||||
<string name="cover_as_background">Cover as background</string>
|
||||
|
||||
<!-- On-Demand configuration -->
|
||||
<string name="on_demand_config_setting_changed">Setting updated successfully.</string>
|
||||
|
||||
@ -26,6 +26,7 @@ dependencies {
|
||||
implementation project(":ui:common")
|
||||
implementation project(":ui:episodes")
|
||||
implementation project(':ui:i18n')
|
||||
implementation project(':ui:glide')
|
||||
|
||||
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
|
||||
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
||||
|
||||
@ -23,6 +23,7 @@ public class PlayerWidget extends AppWidgetProvider {
|
||||
public static final String KEY_WIDGET_SKIP = "widget_skip";
|
||||
public static final String KEY_WIDGET_FAST_FORWARD = "widget_fast_forward";
|
||||
public static final String KEY_WIDGET_REWIND = "widget_rewind";
|
||||
public static final String KEY_WIDGET_COVER_BACKGROUND = "widget_cover_background";
|
||||
public static final int DEFAULT_COLOR = 0xff262C31;
|
||||
private static final String WORKAROUND_WORK_NAME = "WidgetUpdaterWorkaround";
|
||||
|
||||
@ -65,6 +66,7 @@ public class PlayerWidget extends AppWidgetProvider {
|
||||
prefs.edit().remove(KEY_WIDGET_REWIND + appWidgetId).apply();
|
||||
prefs.edit().remove(KEY_WIDGET_FAST_FORWARD + appWidgetId).apply();
|
||||
prefs.edit().remove(KEY_WIDGET_SKIP + appWidgetId).apply();
|
||||
prefs.edit().remove(KEY_WIDGET_COVER_BACKGROUND + appWidgetId).apply();
|
||||
}
|
||||
AppWidgetManager manager = AppWidgetManager.getInstance(context);
|
||||
int[] widgetIds = manager.getAppWidgetIds(new ComponentName(context, PlayerWidget.class));
|
||||
|
||||
@ -10,9 +10,16 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.load.Transformation;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.ui.common.ToolbarActivity;
|
||||
import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@ -26,6 +33,7 @@ public class WidgetConfigActivity extends ToolbarActivity {
|
||||
private CheckBox ckRewind;
|
||||
private CheckBox ckFastForward;
|
||||
private CheckBox ckSkip;
|
||||
private CheckBox ckCoverAsBcg;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -85,6 +93,8 @@ public class WidgetConfigActivity extends ToolbarActivity {
|
||||
ckFastForward.setOnClickListener(v -> displayPreviewPanel());
|
||||
ckSkip = findViewById(R.id.ckSkip);
|
||||
ckSkip.setOnClickListener(v -> displayPreviewPanel());
|
||||
ckCoverAsBcg = findViewById(R.id.ckCoverAsBcg);
|
||||
ckCoverAsBcg.setOnClickListener(v -> displayPreviewPanel());
|
||||
|
||||
setInitialState();
|
||||
}
|
||||
@ -95,6 +105,7 @@ public class WidgetConfigActivity extends ToolbarActivity {
|
||||
ckRewind.setChecked(prefs.getBoolean(PlayerWidget.KEY_WIDGET_REWIND + appWidgetId, false));
|
||||
ckFastForward.setChecked(prefs.getBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + appWidgetId, false));
|
||||
ckSkip.setChecked(prefs.getBoolean(PlayerWidget.KEY_WIDGET_SKIP + appWidgetId, false));
|
||||
ckCoverAsBcg.setChecked(prefs.getBoolean(PlayerWidget.KEY_WIDGET_COVER_BACKGROUND + appWidgetId, false));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
int color = prefs.getInt(PlayerWidget.KEY_WIDGET_COLOR + appWidgetId, PlayerWidget.DEFAULT_COLOR);
|
||||
int opacity = Color.alpha(color) * 100 / 0xFF;
|
||||
@ -116,6 +127,31 @@ public class WidgetConfigActivity extends ToolbarActivity {
|
||||
.setVisibility(ckFastForward.isChecked() ? View.VISIBLE : View.GONE);
|
||||
widgetPreview.findViewById(R.id.butSkip).setVisibility(ckSkip.isChecked() ? View.VISIBLE : View.GONE);
|
||||
widgetPreview.findViewById(R.id.butRew).setVisibility(ckRewind.isChecked() ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (ckCoverAsBcg.isChecked()) {
|
||||
widgetPreview.findViewById(R.id.imgvCover).setVisibility(View.GONE);
|
||||
widgetPreview.findViewById(R.id.imgvBackground).setVisibility(View.VISIBLE);
|
||||
loadCover(R.id.imgvBackground, new FastBlurTransformation());
|
||||
opacitySeekBar.setEnabled(false);
|
||||
opacitySeekBar.setProgress(100);
|
||||
} else {
|
||||
widgetPreview.findViewById(R.id.imgvCover).setVisibility(View.VISIBLE);
|
||||
widgetPreview.findViewById(R.id.imgvBackground).setVisibility(View.GONE);
|
||||
widgetPreview.findViewById(R.id.widgetLayout).setBackgroundColor(PlayerWidget.DEFAULT_COLOR);
|
||||
opacitySeekBar.setEnabled(true);
|
||||
int radius = getResources().getDimensionPixelSize(R.dimen.widget_inner_radius);
|
||||
loadCover(R.id.imgvCover, new RoundedCorners(radius));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCover(int viewId, Transformation<android.graphics.Bitmap> transform) {
|
||||
ImageView target = findViewById(viewId);
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(Feed.PREFIX_GENERATIVE_COVER)
|
||||
.dontAnimate()
|
||||
.transform(new FitCenter(), transform)
|
||||
.into(target);
|
||||
}
|
||||
|
||||
private void confirmCreateWidget() {
|
||||
@ -128,6 +164,7 @@ public class WidgetConfigActivity extends ToolbarActivity {
|
||||
editor.putBoolean(PlayerWidget.KEY_WIDGET_SKIP + appWidgetId, ckSkip.isChecked());
|
||||
editor.putBoolean(PlayerWidget.KEY_WIDGET_REWIND + appWidgetId, ckRewind.isChecked());
|
||||
editor.putBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + appWidgetId, ckFastForward.isChecked());
|
||||
editor.putBoolean(PlayerWidget.KEY_WIDGET_COVER_BACKGROUND + appWidgetId, ckCoverAsBcg.isChecked());
|
||||
editor.apply();
|
||||
|
||||
Intent resultValue = new Intent();
|
||||
|
||||
@ -13,13 +13,13 @@ import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
||||
import com.bumptech.glide.load.Transformation;
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import de.danoeh.antennapod.ui.appstartintent.MediaButtonStarter;
|
||||
import de.danoeh.antennapod.ui.common.Converter;
|
||||
import de.danoeh.antennapod.storage.preferences.UserPreferences;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.model.playback.MediaType;
|
||||
@ -30,6 +30,7 @@ import de.danoeh.antennapod.ui.appstartintent.PlaybackSpeedActivityStarter;
|
||||
import de.danoeh.antennapod.ui.appstartintent.VideoPlayerActivityStarter;
|
||||
import de.danoeh.antennapod.ui.episodes.ImageResourceUtils;
|
||||
import de.danoeh.antennapod.ui.episodes.TimeSpeedConverter;
|
||||
import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
|
||||
|
||||
/**
|
||||
* Updates the state of the player widget.
|
||||
@ -79,40 +80,10 @@ public abstract class WidgetUpdater {
|
||||
views = new RemoteViews(context.getPackageName(), R.layout.player_widget);
|
||||
|
||||
if (widgetState.media != null) {
|
||||
Bitmap icon;
|
||||
int iconSize = context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
|
||||
views.setOnClickPendingIntent(R.id.layout_left, startMediaPlayer);
|
||||
views.setOnClickPendingIntent(R.id.imgvCover, startMediaPlayer);
|
||||
views.setOnClickPendingIntent(R.id.butPlaybackSpeed, startPlaybackSpeedDialog);
|
||||
|
||||
int radius = context.getResources().getDimensionPixelSize(R.dimen.widget_inner_radius);
|
||||
RequestOptions options = new RequestOptions()
|
||||
.dontAnimate()
|
||||
.transform(new FitCenter(), new RoundedCorners(radius));
|
||||
|
||||
try {
|
||||
icon = Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(widgetState.media.getImageLocation())
|
||||
.apply(options)
|
||||
.submit(iconSize, iconSize)
|
||||
.get(500, TimeUnit.MILLISECONDS);
|
||||
views.setImageViewBitmap(R.id.imgvCover, icon);
|
||||
} catch (Throwable tr1) {
|
||||
try {
|
||||
icon = Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(ImageResourceUtils.getFallbackImageLocation(widgetState.media))
|
||||
.apply(options)
|
||||
.submit(iconSize, iconSize)
|
||||
.get(500, TimeUnit.MILLISECONDS);
|
||||
views.setImageViewBitmap(R.id.imgvCover, icon);
|
||||
} catch (Throwable tr2) {
|
||||
Log.e(TAG, "Error loading the media icon for the widget", tr2);
|
||||
views.setImageViewResource(R.id.imgvCover, R.mipmap.ic_launcher);
|
||||
}
|
||||
}
|
||||
|
||||
views.setTextViewText(R.id.txtvTitle, widgetState.media.getEpisodeTitle());
|
||||
views.setViewVisibility(R.id.txtvTitle, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.txtNoPlaying, View.GONE);
|
||||
@ -177,6 +148,7 @@ public abstract class WidgetUpdater {
|
||||
boolean showRewind = prefs.getBoolean(PlayerWidget.KEY_WIDGET_REWIND + id, false);
|
||||
boolean showFastForward = prefs.getBoolean(PlayerWidget.KEY_WIDGET_FAST_FORWARD + id, false);
|
||||
boolean showSkip = prefs.getBoolean(PlayerWidget.KEY_WIDGET_SKIP + id, false);
|
||||
boolean showCoverAsBcg = prefs.getBoolean(PlayerWidget.KEY_WIDGET_COVER_BACKGROUND + id, false);
|
||||
|
||||
if (showPlaybackSpeed || showRewind || showSkip || showFastForward) {
|
||||
views.setInt(R.id.extendedButtonsContainer, "setVisibility", View.VISIBLE);
|
||||
@ -190,6 +162,34 @@ public abstract class WidgetUpdater {
|
||||
views.setInt(R.id.butPlay, "setVisibility", View.VISIBLE);
|
||||
}
|
||||
|
||||
if (showCoverAsBcg) {
|
||||
views.setViewVisibility(R.id.imgvCover, View.GONE);
|
||||
views.setViewVisibility(R.id.imgvBackground, View.VISIBLE);
|
||||
int iconSize = 4 * context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
|
||||
Bitmap icon = null;
|
||||
if (widgetState.media != null) {
|
||||
icon = loadCover(context, iconSize, widgetState.media, new FastBlurTransformation());
|
||||
}
|
||||
if (icon != null) {
|
||||
views.setImageViewBitmap(R.id.imgvBackground, icon);
|
||||
} else {
|
||||
views.setViewVisibility(R.id.imgvBackground, View.GONE);
|
||||
}
|
||||
} else {
|
||||
views.setViewVisibility(R.id.imgvCover, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.imgvBackground, View.GONE);
|
||||
int iconSize = context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
|
||||
int radius = context.getResources().getDimensionPixelSize(R.dimen.widget_inner_radius);
|
||||
Bitmap icon = null;
|
||||
if (widgetState.media != null) {
|
||||
icon = loadCover(context, iconSize, widgetState.media, new RoundedCorners(radius));
|
||||
}
|
||||
if (icon != null) {
|
||||
views.setImageViewBitmap(R.id.imgvCover, icon);
|
||||
} else {
|
||||
views.setImageViewResource(R.id.imgvCover, R.mipmap.ic_launcher);
|
||||
}
|
||||
}
|
||||
int backgroundColor = prefs.getInt(PlayerWidget.KEY_WIDGET_COLOR + id, PlayerWidget.DEFAULT_COLOR);
|
||||
views.setInt(R.id.widgetLayout, "setBackgroundColor", backgroundColor);
|
||||
|
||||
@ -197,6 +197,31 @@ public abstract class WidgetUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private static Bitmap loadCover(Context context, int iconSize, Playable media, Transformation<Bitmap> transform) {
|
||||
try {
|
||||
return Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(media.getImageLocation())
|
||||
.dontAnimate()
|
||||
.transform(transform)
|
||||
.submit(iconSize, iconSize)
|
||||
.get(500, TimeUnit.MILLISECONDS);
|
||||
} catch (Throwable tr1) {
|
||||
try {
|
||||
return Glide.with(context)
|
||||
.asBitmap()
|
||||
.load(ImageResourceUtils.getFallbackImageLocation(media))
|
||||
.dontAnimate()
|
||||
.transform(transform)
|
||||
.submit(iconSize, iconSize)
|
||||
.get(500, TimeUnit.MILLISECONDS);
|
||||
} catch (Throwable tr2) {
|
||||
Log.e(TAG, "Error loading the media icon for the widget", tr2);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of cells needed for given size of the widget.
|
||||
*
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:importantForAccessibility="no"
|
||||
app:srcCompat="@drawable/teaser" />
|
||||
|
||||
<include
|
||||
@ -47,7 +48,6 @@
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_opacity"
|
||||
@ -108,6 +108,13 @@
|
||||
android:layout_weight="1"
|
||||
android:text="@string/skip_episode_label" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/ckCoverAsBcg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cover_as_background" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
|
||||
@ -13,6 +13,15 @@
|
||||
android:background="#262C31"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:alpha="0.6"
|
||||
android:scaleType="centerCrop"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butPlay"
|
||||
android:layout_width="@android:dimen/app_icon_size"
|
||||
@ -38,16 +47,19 @@
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
android:layout_width="@android:dimen/app_icon_size"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="@android:dimen/app_icon_size"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:importantForAccessibility="no"
|
||||
android:layout_margin="12dp" />
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginVertical="12dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user