Android: Generate placeholder covers

This commit is contained in:
Connor McLaughlin 2021-03-06 15:30:28 +10:00
parent b188c908c0
commit ef440d2712
3 changed files with 74 additions and 12 deletions

View file

@ -1,7 +1,5 @@
package com.github.stenzek.duckstation; package com.github.stenzek.duckstation;
import android.content.Context;
import android.content.res.Configuration;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.util.TypedValue; import android.util.TypedValue;
@ -17,16 +15,13 @@ import androidx.annotation.Nullable;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
public class GameGridFragment extends Fragment implements GameList.OnRefreshListener { public class GameGridFragment extends Fragment implements GameList.OnRefreshListener {
private static final int SPACING_DIPS = 25; private static final int SPACING_DIPS = 25;
private static final int WIDTH_DIPS = 160; private static final int WIDTH_DIPS = 160;
private MainActivity mParent; private final MainActivity mParent;
private RecyclerView mRecyclerView; private RecyclerView mRecyclerView;
private ViewAdapter mAdapter; private ViewAdapter mAdapter;
private GridAutofitLayoutManager mLayoutManager; private GridAutofitLayoutManager mLayoutManager;
@ -69,8 +64,8 @@ public class GameGridFragment extends Fragment implements GameList.OnRefreshList
} }
private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private MainActivity mParent; private final MainActivity mParent;
private ImageView mImageView; private final ImageView mImageView;
private GameListEntry mEntry; private GameListEntry mEntry;
public ViewHolder(@NonNull MainActivity parent, @NonNull View itemView) { public ViewHolder(@NonNull MainActivity parent, @NonNull View itemView) {
@ -84,9 +79,12 @@ public class GameGridFragment extends Fragment implements GameList.OnRefreshList
public void bindToEntry(GameListEntry entry) { public void bindToEntry(GameListEntry entry) {
mEntry = entry; mEntry = entry;
// while it loads/generates
mImageView.setImageDrawable(ContextCompat.getDrawable(mParent, R.drawable.ic_media_cdrom));
final String coverPath = entry.getCoverPath(); final String coverPath = entry.getCoverPath();
if (coverPath == null) { if (coverPath == null) {
mImageView.setImageDrawable(ContextCompat.getDrawable(mParent, R.drawable.ic_media_cdrom)); new GenerateCoverTask(mParent, mImageView, mEntry.getTitle()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return; return;
} }
@ -125,9 +123,9 @@ public class GameGridFragment extends Fragment implements GameList.OnRefreshList
} }
private static class ViewAdapter extends RecyclerView.Adapter<ViewHolder> { private static class ViewAdapter extends RecyclerView.Adapter<ViewHolder> {
private MainActivity mParent; private final MainActivity mParent;
private LayoutInflater mInflater; private final LayoutInflater mInflater;
private GameList mGameList; private final GameList mGameList;
public ViewAdapter(@NonNull MainActivity parent, @NonNull GameList gameList) { public ViewAdapter(@NonNull MainActivity parent, @NonNull GameList gameList) {
mParent = parent; mParent = parent;

View file

@ -0,0 +1,64 @@
package com.github.stenzek.duckstation;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
public class GenerateCoverTask extends AsyncTask<Void, Void, Bitmap> {
private final Context mContext;
private final WeakReference<ImageView> mView;
private final String mTitle;
public GenerateCoverTask(Context context, ImageView view, String title) {
mContext = context;
mView = new WeakReference<>(view);
mTitle = title;
}
@Override
protected Bitmap doInBackground(Void... voids) {
try {
final Bitmap background = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.cover_placeholder);
if (background == null)
return null;
final Bitmap bitmap = Bitmap.createBitmap(background.getWidth(), background.getHeight(), background.getConfig());
final Canvas canvas = new Canvas(bitmap);
final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(background, 0.0f, 0.0f, paint);
paint.setColor(Color.rgb(255, 255, 255));
paint.setTextSize(100);
paint.setShadowLayer(1.0f, 0.0f, 1.0f, Color.DKGRAY);
paint.setTextAlign(Paint.Align.CENTER);
final StaticLayout staticLayout = new StaticLayout(mTitle, paint,
canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
canvas.save();
canvas.translate(canvas.getWidth() / 2, (canvas.getHeight() / 2) - (staticLayout.getHeight() / 2));
staticLayout.draw(canvas);
canvas.restore();
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
ImageView iv = mView.get();
if (iv != null)
iv.setImageBitmap(bitmap);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB