Convert subscriptions screen to cards (#6261)

This commit is contained in:
GitStart 2023-02-11 19:04:14 +01:00 committed by GitHub
parent f9839aba99
commit 4096aaf47e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 197 additions and 264 deletions

View File

@ -1,40 +1,28 @@
package de.danoeh.antennapod.adapter; package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.palette.graphics.Palette;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder; import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.CustomViewTarget; import com.bumptech.glide.request.target.CustomViewTarget;
import com.bumptech.glide.request.transition.Transition;
import de.danoeh.antennapod.activity.MainActivity;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import com.bumptech.glide.request.transition.Transition;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.ui.common.ThemeUtils;
import de.danoeh.antennapod.ui.glide.PaletteBitmap;
public class CoverLoader { public class CoverLoader {
private int resource = 0; private int resource = 0;
private String uri; private String uri;
private String fallbackUri; private String fallbackUri;
private TextView txtvPlaceholder;
private ImageView imgvCover; private ImageView imgvCover;
private boolean textAndImageCombined; private boolean textAndImageCombined;
private MainActivity activity; private MainActivity activity;
private TextView fallbackTitle;
public CoverLoader(MainActivity activity) { public CoverLoader(MainActivity activity) {
this.activity = activity; this.activity = activity;
@ -60,31 +48,30 @@ public class CoverLoader {
return this; return this;
} }
public CoverLoader withPlaceholderView(TextView placeholderView) { public CoverLoader withPlaceholderView(TextView title) {
txtvPlaceholder = placeholderView; this.fallbackTitle = title;
return this; return this;
} }
/** /**
* Set cover text and if it should be shown even if there is a cover image. * Set cover text and if it should be shown even if there is a cover image.
* * @param fallbackTitle Fallback title text
* @param placeholderView Cover text.
* @param textAndImageCombined Show cover text even if there is a cover image? * @param textAndImageCombined Show cover text even if there is a cover image?
*/ */
@NonNull @NonNull
public CoverLoader withPlaceholderView(@NonNull TextView placeholderView, boolean textAndImageCombined) { public CoverLoader withPlaceholderView(TextView fallbackTitle, boolean textAndImageCombined) {
this.txtvPlaceholder = placeholderView; this.fallbackTitle = fallbackTitle;
this.textAndImageCombined = textAndImageCombined; this.textAndImageCombined = textAndImageCombined;
return this; return this;
} }
public void load() { public void load() {
CoverTarget coverTarget = new CoverTarget(txtvPlaceholder, imgvCover, textAndImageCombined); CoverTarget coverTarget = new CoverTarget(fallbackTitle, imgvCover, textAndImageCombined);
if (resource != 0) { if (resource != 0) {
Glide.with(activity).clear(coverTarget); Glide.with(activity).clear(coverTarget);
imgvCover.setImageResource(resource); imgvCover.setImageResource(resource);
CoverTarget.setPlaceholderVisibility(txtvPlaceholder, textAndImageCombined, null); CoverTarget.setTitleVisibility(fallbackTitle, textAndImageCombined);
return; return;
} }
@ -92,14 +79,14 @@ public class CoverLoader {
.fitCenter() .fitCenter()
.dontAnimate(); .dontAnimate();
RequestBuilder<PaletteBitmap> builder = Glide.with(activity) RequestBuilder<Drawable> builder = Glide.with(activity)
.as(PaletteBitmap.class) .as(Drawable.class)
.load(uri) .load(uri)
.apply(options); .apply(options);
if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) { if (fallbackUri != null) {
builder = builder.error(Glide.with(activity) builder = builder.error(Glide.with(activity)
.as(PaletteBitmap.class) .as(Drawable.class)
.load(fallbackUri) .load(fallbackUri)
.apply(options)); .apply(options));
} }
@ -107,64 +94,41 @@ public class CoverLoader {
builder.into(coverTarget); builder.into(coverTarget);
} }
static class CoverTarget extends CustomViewTarget<ImageView, PaletteBitmap> { static class CoverTarget extends CustomViewTarget<ImageView, Drawable> {
private final WeakReference<TextView> placeholder; private final WeakReference<TextView> fallbackTitle;
private final WeakReference<ImageView> cover; private final WeakReference<ImageView> cover;
private boolean textAndImageCombined; private final boolean textAndImageCombined;
public CoverTarget(TextView txtvPlaceholder, ImageView imgvCover, boolean textAndImageCombined) { public CoverTarget(TextView fallbackTitle, ImageView coverImage, boolean textAndImageCombined) {
super(imgvCover); super(coverImage);
if (txtvPlaceholder != null) { this.fallbackTitle = new WeakReference<>(fallbackTitle);
txtvPlaceholder.setVisibility(View.VISIBLE); this.cover = new WeakReference<>(coverImage);
}
placeholder = new WeakReference<>(txtvPlaceholder);
cover = new WeakReference<>(imgvCover);
this.textAndImageCombined = textAndImageCombined; this.textAndImageCombined = textAndImageCombined;
} }
@Override @Override
public void onLoadFailed(Drawable errorDrawable) { public void onLoadFailed(Drawable errorDrawable) {
setPlaceholderVisibility(this.placeholder.get(), true, null); setTitleVisibility(fallbackTitle.get(), true);
} }
@Override @Override
public void onResourceReady(@NonNull PaletteBitmap resource, public void onResourceReady(@NonNull Drawable resource,
@Nullable Transition<? super PaletteBitmap> transition) { @Nullable Transition<? super Drawable> transition) {
ImageView ivCover = cover.get(); ImageView ivCover = cover.get();
ivCover.setImageBitmap(resource.bitmap); ivCover.setImageDrawable(resource);
setPlaceholderVisibility(placeholder.get(), textAndImageCombined, resource.palette); setTitleVisibility(fallbackTitle.get(), textAndImageCombined);
} }
@Override @Override
protected void onResourceCleared(@Nullable Drawable placeholder) { protected void onResourceCleared(@Nullable Drawable placeholder) {
ImageView ivCover = cover.get(); ImageView ivCover = cover.get();
ivCover.setImageDrawable(placeholder); ivCover.setImageDrawable(placeholder);
setPlaceholderVisibility(this.placeholder.get(), textAndImageCombined, null); setTitleVisibility(fallbackTitle.get(), textAndImageCombined);
} }
static void setPlaceholderVisibility(TextView placeholder, boolean textAndImageCombined, Palette palette) { static void setTitleVisibility(TextView fallbackTitle, boolean textAndImageCombined) {
boolean showTitle = UserPreferences.shouldShowSubscriptionTitle(); if (fallbackTitle != null) {
if (placeholder != null) { fallbackTitle.setVisibility(textAndImageCombined ? View.VISIBLE : View.GONE);
if (textAndImageCombined || showTitle) {
final Context context = placeholder.getContext();
placeholder.setVisibility(View.VISIBLE);
int bgColor = ContextCompat.getColor(context, R.color.feed_text_bg);
if (palette == null || !showTitle) {
placeholder.setBackgroundColor(bgColor);
placeholder.setTextColor(ThemeUtils.getColorFromAttr(placeholder.getContext(),
android.R.attr.textColorPrimary));
return;
}
int dominantColor = palette.getDominantColor(bgColor);
int textColor = ContextCompat.getColor(context, R.color.white);
if (ColorUtils.calculateLuminance(dominantColor) > 0.5) {
textColor = ContextCompat.getColor(context, R.color.black);
}
placeholder.setTextColor(textColor);
placeholder.setBackgroundColor(dominantColor);
} else {
placeholder.setVisibility(View.INVISIBLE);
}
} }
} }
} }

View File

@ -5,7 +5,6 @@ import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.text.TextUtils;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -17,20 +16,19 @@ import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat; import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.elevation.SurfaceColors;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.MainActivity;
@ -39,7 +37,6 @@ import de.danoeh.antennapod.core.storage.NavDrawerData;
import de.danoeh.antennapod.fragment.FeedItemlistFragment; import de.danoeh.antennapod.fragment.FeedItemlistFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.ui.common.TriangleLabelView;
/** /**
* Adapter for subscriptions * Adapter for subscriptions
@ -52,6 +49,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
private List<NavDrawerData.DrawerItem> listItems; private List<NavDrawerData.DrawerItem> listItems;
private NavDrawerData.DrawerItem selectedItem = null; private NavDrawerData.DrawerItem selectedItem = null;
int longPressedPosition = 0; // used to init actionMode int longPressedPosition = 0; // used to init actionMode
private int columnCount = 3;
public SubscriptionsRecyclerAdapter(MainActivity mainActivity) { public SubscriptionsRecyclerAdapter(MainActivity mainActivity) {
super(mainActivity); super(mainActivity);
@ -60,6 +58,10 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
setHasStableIds(true); setHasStableIds(true);
} }
public void setColumnCount(int columnCount) {
this.columnCount = columnCount;
}
public Object getItem(int position) { public Object getItem(int position) {
return listItems.get(position); return listItems.get(position);
} }
@ -72,24 +74,7 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
@Override @Override
public SubscriptionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public SubscriptionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mainActivityRef.get()).inflate(R.layout.subscription_item, parent, false); View itemView = LayoutInflater.from(mainActivityRef.get()).inflate(R.layout.subscription_item, parent, false);
TextView feedTitle = itemView.findViewById(R.id.txtvTitle); itemView.findViewById(R.id.titleLabel).setVisibility(viewType == COVER_WITH_TITLE ? View.VISIBLE : View.GONE);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) feedTitle.getLayoutParams();
int topAndBottomItemId = R.id.imgvCover;
int belowItemId = 0;
if (viewType == COVER_WITH_TITLE) {
topAndBottomItemId = 0;
belowItemId = R.id.imgvCover;
feedTitle.setBackgroundColor(
ContextCompat.getColor(feedTitle.getContext(), R.color.feed_text_bg));
int padding = (int) convertDpToPixel(feedTitle.getContext(), 6);
feedTitle.setPadding(padding, padding, padding, padding);
}
params.addRule(RelativeLayout.BELOW, belowItemId);
params.addRule(RelativeLayout.ALIGN_TOP, topAndBottomItemId);
params.addRule(RelativeLayout.ALIGN_BOTTOM, topAndBottomItemId);
feedTitle.setLayoutParams(params);
feedTitle.setSingleLine(viewType == COVER_WITH_TITLE);
return new SubscriptionViewHolder(itemView); return new SubscriptionViewHolder(itemView);
} }
@ -107,11 +92,11 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
holder.selectCheckbox.setChecked((isSelected(position))); holder.selectCheckbox.setChecked((isSelected(position)));
holder.selectCheckbox.setOnCheckedChangeListener((buttonView, isChecked) holder.selectCheckbox.setOnCheckedChangeListener((buttonView, isChecked)
-> setSelected(holder.getBindingAdapterPosition(), isChecked)); -> setSelected(holder.getBindingAdapterPosition(), isChecked));
holder.imageView.setAlpha(0.6f); holder.coverImage.setAlpha(0.6f);
holder.count.setVisibility(View.GONE); holder.count.setVisibility(View.GONE);
} else { } else {
holder.selectView.setVisibility(View.GONE); holder.selectView.setVisibility(View.GONE);
holder.imageView.setAlpha(1.0f); holder.coverImage.setAlpha(1.0f);
} }
holder.itemView.setOnLongClickListener(v -> { holder.itemView.setOnLongClickListener(v -> {
@ -224,55 +209,74 @@ public class SubscriptionsRecyclerAdapter extends SelectableAdapter<Subscription
} }
public class SubscriptionViewHolder extends RecyclerView.ViewHolder { public class SubscriptionViewHolder extends RecyclerView.ViewHolder {
private final TextView feedTitle; private final TextView title;
private final ImageView imageView; private final ImageView coverImage;
private final TriangleLabelView count; private final TextView count;
private final TextView fallbackTitle;
private final FrameLayout selectView; private final FrameLayout selectView;
private final CheckBox selectCheckbox; private final CheckBox selectCheckbox;
private final CardView card;
public SubscriptionViewHolder(@NonNull View itemView) { public SubscriptionViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
feedTitle = itemView.findViewById(R.id.txtvTitle); title = itemView.findViewById(R.id.titleLabel);
imageView = itemView.findViewById(R.id.imgvCover); coverImage = itemView.findViewById(R.id.coverImage);
count = itemView.findViewById(R.id.triangleCountView); count = itemView.findViewById(R.id.countViewPill);
selectView = itemView.findViewById(R.id.selectView); fallbackTitle = itemView.findViewById(R.id.fallbackTitleLabel);
selectView = itemView.findViewById(R.id.selectContainer);
selectCheckbox = itemView.findViewById(R.id.selectCheckBox); selectCheckbox = itemView.findViewById(R.id.selectCheckBox);
card = itemView.findViewById(R.id.outerContainer);
} }
public void bind(NavDrawerData.DrawerItem drawerItem) { public void bind(NavDrawerData.DrawerItem drawerItem) {
Drawable drawable = AppCompatResources.getDrawable(selectView.getContext(), Drawable drawable = AppCompatResources.getDrawable(selectView.getContext(),
R.drawable.ic_checkbox_background); R.drawable.ic_checkbox_background);
selectView.setBackground(drawable); // Setting this in XML crashes API <= 21 selectView.setBackground(drawable); // Setting this in XML crashes API <= 21
feedTitle.setText(drawerItem.getTitle()); title.setText(drawerItem.getTitle());
imageView.setContentDescription(drawerItem.getTitle()); fallbackTitle.setText(drawerItem.getTitle());
feedTitle.setVisibility(View.VISIBLE); coverImage.setContentDescription(drawerItem.getTitle());
if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL) {
count.setCorner(TriangleLabelView.Corner.TOP_LEFT);
}
if (drawerItem.getCounter() > 0) { if (drawerItem.getCounter() > 0) {
count.setPrimaryText(NumberFormat.getInstance().format(drawerItem.getCounter())); count.setText(NumberFormat.getInstance().format(drawerItem.getCounter()));
count.setVisibility(View.VISIBLE); count.setVisibility(View.VISIBLE);
} else { } else {
count.setVisibility(View.GONE); count.setVisibility(View.GONE);
} }
CoverLoader coverLoader = new CoverLoader(mainActivityRef.get());
boolean textAndImageCombined;
if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) { if (drawerItem.type == NavDrawerData.DrawerItem.Type.FEED) {
Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed; Feed feed = ((NavDrawerData.FeedDrawerItem) drawerItem).feed;
boolean textAndImageCombind = feed.isLocalFeed() textAndImageCombined = feed.isLocalFeed() && feed.getImageUrl() != null
&& feed.getImageUrl() != null && feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER); && feed.getImageUrl().startsWith(Feed.PREFIX_GENERATIVE_COVER);
new CoverLoader(mainActivityRef.get()) coverLoader.withUri(feed.getImageUrl());
.withUri(feed.getImageUrl())
.withPlaceholderView(feedTitle, textAndImageCombind)
.withCoverView(imageView)
.load();
} else { } else {
new CoverLoader(mainActivityRef.get()) textAndImageCombined = true;
.withResource(R.drawable.ic_tag) coverLoader.withResource(R.drawable.ic_tag);
.withPlaceholderView(feedTitle, true)
.withCoverView(imageView)
.load();
} }
if (UserPreferences.shouldShowSubscriptionTitle()) {
// No need for fallback title when already showing title
fallbackTitle.setVisibility(View.GONE);
} else {
coverLoader.withPlaceholderView(fallbackTitle, textAndImageCombined);
}
coverLoader.withCoverView(coverImage);
coverLoader.load();
float density = mainActivityRef.get().getResources().getDisplayMetrics().density;
card.setCardBackgroundColor(SurfaceColors.getColorForElevation(mainActivityRef.get(), 1 * density));
int textPadding = columnCount <= 3 ? 16 : 8;
title.setPadding(textPadding, textPadding, textPadding, textPadding);
fallbackTitle.setPadding(textPadding, textPadding, textPadding, textPadding);
int textSize = 14;
if (columnCount == 3) {
textSize = 15;
} else if (columnCount == 2) {
textSize = 16;
}
title.setTextSize(textSize);
fallbackTitle.setTextSize(textSize);
} }
} }

View File

@ -142,7 +142,6 @@ public class SubscriptionFragment extends Fragment
} }
subscriptionRecycler = root.findViewById(R.id.subscriptions_grid); subscriptionRecycler = root.findViewById(R.id.subscriptions_grid);
setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
subscriptionRecycler.addItemDecoration(new SubscriptionsRecyclerAdapter.GridDividerItemDecorator()); subscriptionRecycler.addItemDecoration(new SubscriptionsRecyclerAdapter.GridDividerItemDecorator());
registerForContextMenu(subscriptionRecycler); registerForContextMenu(subscriptionRecycler);
subscriptionRecycler.addOnScrollListener(new LiftOnScrollListener(root.findViewById(R.id.appbar))); subscriptionRecycler.addOnScrollListener(new LiftOnScrollListener(root.findViewById(R.id.appbar)));
@ -153,6 +152,7 @@ public class SubscriptionFragment extends Fragment
MenuItemUtils.setOnClickListeners(menu, SubscriptionFragment.this::onContextItemSelected); MenuItemUtils.setOnClickListeners(menu, SubscriptionFragment.this::onContextItemSelected);
} }
}; };
setColumnNumber(prefs.getInt(PREF_NUM_COLUMNS, getDefaultNumOfColumns()));
subscriptionAdapter.setOnSelectModeListener(this); subscriptionAdapter.setOnSelectModeListener(this);
subscriptionRecycler.setAdapter(subscriptionAdapter); subscriptionRecycler.setAdapter(subscriptionAdapter);
setupEmptyView(); setupEmptyView();
@ -251,6 +251,7 @@ public class SubscriptionFragment extends Fragment
private void setColumnNumber(int columns) { private void setColumnNumber(int columns) {
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(),
columns, RecyclerView.VERTICAL, false); columns, RecyclerView.VERTICAL, false);
subscriptionAdapter.setColumnCount(columns);
subscriptionRecycler.setLayoutManager(gridLayoutManager); subscriptionRecycler.setLayoutManager(gridLayoutManager);
prefs.edit().putInt(PREF_NUM_COLUMNS, columns).apply(); prefs.edit().putInt(PREF_NUM_COLUMNS, columns).apply();
refreshToolbarState(); refreshToolbarState();

View File

@ -1,64 +1,107 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:squareImageView="http://schemas.android.com/apk/de.danoeh.antennapod" xmlns:squareImageView="http://schemas.android.com/apk/de.danoeh.antennapod"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackground"> android:padding="4dp">
<de.danoeh.antennapod.ui.common.SquareImageView <androidx.cardview.widget.CardView
android:id="@+id/imgvCover" android:id="@+id/outerContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/non_square_icon_background" android:clickable="false"
android:scaleType="fitCenter" android:foreground="?attr/selectableItemBackground"
squareImageView:direction="width" app:cardCornerRadius="12dp"
tools:src="@tools:sample/avatars" /> app:cardElevation="0dp">
<com.joanzapata.iconify.widget.IconTextView <LinearLayout
android:id="@+id/txtvTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignStart="@+id/imgvCover"
android:layout_alignLeft="@+id/imgvCover"
android:layout_alignTop="@+id/imgvCover"
android:layout_alignEnd="@+id/imgvCover"
android:layout_alignRight="@+id/imgvCover"
android:layout_alignBottom="@+id/imgvCover"
android:background="@color/non_square_icon_background"
android:ellipsize="end"
android:gravity="center"
android:textColor="?android:attr/textColorPrimary"
tools:text="@string/app_name" />
<de.danoeh.antennapod.ui.common.TriangleLabelView
android:id="@+id/triangleCountView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
app:backgroundColor="?attr/colorSecondary"
app:corner="rightTop"
app:primaryText="Test"
app:primaryTextColor="?attr/colorOnSecondary"
app:primaryTextSize="12sp" />
<FrameLayout
android:id="@+id/selectView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/selectCheckBox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minWidth="0dp" android:orientation="vertical">
android:minHeight="0dp"
android:layout_margin="8dp" />
</FrameLayout> <androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="1px"
android:clickable="false"
app:cardBackgroundColor="@color/non_square_icon_background"
app:cardCornerRadius="12dp"
app:cardElevation="0dp">
</RelativeLayout> <RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<de.danoeh.antennapod.ui.common.SquareImageView
android:id="@+id/coverImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:outlineProvider="background"
squareImageView:direction="width"
tools:src="@tools:sample/avatars" />
<TextView
android:id="@+id/fallbackTitleLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/coverImage"
android:layout_alignLeft="@+id/coverImage"
android:layout_alignTop="@+id/coverImage"
android:layout_alignEnd="@+id/coverImage"
android:layout_alignRight="@+id/coverImage"
android:layout_alignBottom="@+id/coverImage"
android:background="@color/feed_text_bg"
android:gravity="center"
android:ellipsize="end"
android:padding="6dp"
android:textColor="#fff"
tools:text="@sample/episodes.json/data/title" />
<TextView
android:id="@+id/countViewPill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3"
android:layout_alignParentEnd="true"
android:textSize="14sp"
style="@style/TextPill" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/titleLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="start"
android:textColor="?android:attr/textColorPrimary"
android:lines="2"
tools:text="@sample/episodes.json/data/title" />
</LinearLayout>
<FrameLayout
android:id="@+id/selectContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false">
<CheckBox
android:id="@+id/selectCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
android:minHeight="0dp"
android:layout_margin="8dp" />
</FrameLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#D2404040" />
<corners android:radius="18dp" />
</shape>

View File

@ -9,7 +9,7 @@
<color name="black">#000000</color> <color name="black">#000000</color>
<color name="image_readability_tint">#80000000</color> <color name="image_readability_tint">#80000000</color>
<color name="feed_image_bg">#50000000</color> <color name="feed_image_bg">#50000000</color>
<color name="feed_text_bg">#ccbfbfbf</color> <color name="feed_text_bg">#55333333</color>
<!-- Theme colors --> <!-- Theme colors -->
<color name="background_light">#FFFFFF</color> <color name="background_light">#FFFFFF</color>

View File

@ -284,4 +284,13 @@
<item name="android:clickable">true</item> <item name="android:clickable">true</item>
</style> </style>
<style name="TextPill">
<item name="android:background">@drawable/bg_pill_translucent</item>
<item name="android:layout_margin">8dp</item>
<item name="android:textColor">@color/white</item>
<item name="android:textAlignment">center</item>
<item name="android:paddingStart">8dp</item>
<item name="android:paddingEnd">8dp</item>
</style>
</resources> </resources>

View File

@ -2,7 +2,6 @@ package de.danoeh.antennapod.ui.glide;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -51,6 +50,5 @@ public class ApGlideModule extends AppGlideModule {
registry.append(String.class, InputStream.class, new NoHttpStringLoader.StreamFactory()); registry.append(String.class, InputStream.class, new NoHttpStringLoader.StreamFactory());
registry.append(EmbeddedChapterImage.class, ByteBuffer.class, new ChapterImageModelLoader.Factory()); registry.append(EmbeddedChapterImage.class, ByteBuffer.class, new ChapterImageModelLoader.Factory());
registry.register(Bitmap.class, PaletteBitmap.class, new PaletteBitmapTranscoder());
} }
} }

View File

@ -1,20 +0,0 @@
/*
* Source: https://github.com/bumptech/glide/wiki/Custom-targets#palette-example
*/
package de.danoeh.antennapod.ui.glide;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import androidx.palette.graphics.Palette;
public class PaletteBitmap {
public final Palette palette;
public final Bitmap bitmap;
public PaletteBitmap(@NonNull Bitmap bitmap, Palette palette) {
this.bitmap = bitmap;
this.palette = palette;
}
}

View File

@ -1,40 +0,0 @@
/*
* Source: https://github.com/bumptech/glide/wiki/Custom-targets#palette-example
*/
package de.danoeh.antennapod.ui.glide;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.util.Util;
public class PaletteBitmapResource implements Resource<PaletteBitmap> {
private final PaletteBitmap paletteBitmap;
public PaletteBitmapResource(@NonNull PaletteBitmap paletteBitmap) {
this.paletteBitmap = paletteBitmap;
}
@NonNull
@Override
public Class<PaletteBitmap> getResourceClass() {
return PaletteBitmap.class;
}
@NonNull
@Override
public PaletteBitmap get() {
return paletteBitmap;
}
@Override
public int getSize() {
return Util.getBitmapByteSize(paletteBitmap.bitmap);
}
@Override
public void recycle() {
paletteBitmap.bitmap.recycle();
}
}

View File

@ -1,31 +0,0 @@
/*
* Source: https://github.com/bumptech/glide/wiki/Custom-targets#palette-example
*/
package de.danoeh.antennapod.ui.glide;
import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.palette.graphics.Palette;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
public class PaletteBitmapTranscoder implements ResourceTranscoder<Bitmap, PaletteBitmap> {
@Nullable
@Override
public Resource<PaletteBitmap> transcode(@NonNull Resource<Bitmap> toTranscode, @NonNull Options options) {
Bitmap bitmap = toTranscode.get();
Palette palette = null;
if (UserPreferences.shouldShowSubscriptionTitle()) {
palette = new Palette.Builder(bitmap).generate();
}
PaletteBitmap result = new PaletteBitmap(bitmap, palette);
return new PaletteBitmapResource(result);
}
}