Convert subscriptions screen to cards (#6261)
This commit is contained in:
parent
f9839aba99
commit
4096aaf47e
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -1,55 +1,96 @@
|
||||||
<?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_height="match_parent"
|
||||||
|
android:clickable="false"
|
||||||
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<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
|
||||||
|
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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/non_square_icon_background"
|
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
|
android:outlineProvider="background"
|
||||||
squareImageView:direction="width"
|
squareImageView:direction="width"
|
||||||
tools:src="@tools:sample/avatars" />
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
<com.joanzapata.iconify.widget.IconTextView
|
<TextView
|
||||||
android:id="@+id/txtvTitle"
|
android:id="@+id/fallbackTitleLabel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignStart="@+id/imgvCover"
|
android:layout_alignStart="@+id/coverImage"
|
||||||
android:layout_alignLeft="@+id/imgvCover"
|
android:layout_alignLeft="@+id/coverImage"
|
||||||
android:layout_alignTop="@+id/imgvCover"
|
android:layout_alignTop="@+id/coverImage"
|
||||||
android:layout_alignEnd="@+id/imgvCover"
|
android:layout_alignEnd="@+id/coverImage"
|
||||||
android:layout_alignRight="@+id/imgvCover"
|
android:layout_alignRight="@+id/coverImage"
|
||||||
android:layout_alignBottom="@+id/imgvCover"
|
android:layout_alignBottom="@+id/coverImage"
|
||||||
android:background="@color/non_square_icon_background"
|
android:background="@color/feed_text_bg"
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:ellipsize="end"
|
||||||
tools:text="@string/app_name" />
|
android:padding="6dp"
|
||||||
|
android:textColor="#fff"
|
||||||
|
tools:text="@sample/episodes.json/data/title" />
|
||||||
|
|
||||||
<de.danoeh.antennapod.ui.common.TriangleLabelView
|
<TextView
|
||||||
android:id="@+id/triangleCountView"
|
android:id="@+id/countViewPill"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:text="3"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:textSize="14sp"
|
||||||
app:backgroundColor="?attr/colorSecondary"
|
style="@style/TextPill" />
|
||||||
app:corner="rightTop"
|
|
||||||
app:primaryText="Test"
|
</RelativeLayout>
|
||||||
app:primaryTextColor="?attr/colorOnSecondary"
|
|
||||||
app:primaryTextSize="12sp" />
|
</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
|
<FrameLayout
|
||||||
android:id="@+id/selectView"
|
android:id="@+id/selectContainer"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false">
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/selectCheckBox"
|
android:id="@+id/selectCheckBox"
|
||||||
|
@ -61,4 +102,6 @@
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue