/* * Copyright (C) 2014 Fastboot Mobile, LLC. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, see <http://www.gnu.org/licenses>. */ package com.fastbootmobile.encore.app.adapters; import android.app.Activity; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.os.Build; import android.os.Handler; import android.support.v7.graphics.Palette; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import com.fastbootmobile.encore.app.ArtistActivity; import com.fastbootmobile.encore.app.R; import com.fastbootmobile.encore.app.ui.AlbumArtImageView; import com.fastbootmobile.encore.model.Artist; import com.fastbootmobile.encore.utils.Utils; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * Adapter for RecyclerView to display artists in a grid */ public class ArtistsAdapter extends RecyclerView.Adapter<ArtistsAdapter.ViewHolder> { /** * ViewHolder */ public static class ViewHolder extends RecyclerView.ViewHolder { public final LinearLayout llRoot; public final AlbumArtImageView ivCover; public final TextView tvTitle; public Bitmap srcBitmap; public int position; public Artist artist; public int itemColor; public ViewHolder(View item) { super(item); ivCover = (AlbumArtImageView) item.findViewById(R.id.ivCover); tvTitle = (TextView) item.findViewById(R.id.tvTitle); llRoot = (LinearLayout) item.findViewById(R.id.llRoot); srcBitmap = ((BitmapDrawable) item.getResources().getDrawable(R.drawable.album_placeholder)).getBitmap(); ivCover.setTag(this); llRoot.setTag(this); } } private final View.OnClickListener mItemClickListener = new View.OnClickListener() { @Override public void onClick(View v) { final ArtistsAdapter.ViewHolder tag = (ArtistsAdapter.ViewHolder) v.getTag(); final Context ctx = v.getContext(); Artist artist = getItem(tag.position); Intent intent = ArtistActivity.craftIntent(ctx, tag.srcBitmap, artist.getRef(), artist.getProvider(), tag.itemColor); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { AlbumArtImageView ivCover = tag.ivCover; ActivityOptions opt = ActivityOptions.makeSceneTransitionAnimation((Activity) v.getContext(), ivCover, "itemImage"); ctx.startActivity(intent, opt.toBundle()); } else { ctx.startActivity(intent); } } }; private final AlbumArtImageView.OnArtLoadedListener mAlbumArtListener = new AlbumArtImageView.OnArtLoadedListener() { @Override public void onArtLoaded(final AlbumArtImageView view, final BitmapDrawable drawable) { final Resources res = view.getResources(); Palette.from(drawable.getBitmap()).generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { final int defaultColor = res.getColor(R.color.default_album_art_background); final Palette.Swatch darkVibrantColor = palette.getDarkVibrantSwatch(); final Palette.Swatch darkMutedColor = palette.getDarkMutedSwatch(); int targetColor = defaultColor; if (darkVibrantColor != null) { targetColor = darkVibrantColor.getRgb(); } else if (darkMutedColor != null) { targetColor = darkMutedColor.getRgb(); } final TransitionDrawable transition = new TransitionDrawable(new Drawable[]{ new ColorDrawable(res.getColor(R.color.default_album_art_background)), new ColorDrawable(targetColor) }); // Set the background in the UI thread final int finalColor = targetColor; mHandler.post(new Runnable() { @Override public void run() { final ViewHolder holder = (ViewHolder) view.getTag(); holder.srcBitmap = drawable.getBitmap(); holder.itemColor = finalColor; if (finalColor != defaultColor) { Utils.setViewBackground(holder.llRoot, transition); transition.startTransition(1000); } else { holder.llRoot.setBackgroundColor(finalColor); } } }); } }); } }; private final List<Artist> mArtists; private final Handler mHandler; private final Comparator<Artist> mComparator; /** * Default constructor */ public ArtistsAdapter() { mArtists = new ArrayList<>(); mHandler = new Handler(); mComparator = new Comparator<Artist>() { @Override public int compare(Artist artist, Artist artist2) { if (artist.isLoaded() && artist2.isLoaded() && artist.getName() != null && artist2.getName() != null) { return artist.getName().toLowerCase().compareTo(artist2.getName().toLowerCase()); } else { return artist.getRef().compareTo(artist2.getRef()); } } }; } /** * Sorts the list in alphabetical order */ private void sortList() { Collections.sort(mArtists, mComparator); } /** * Adds an item to the adapter * @param a The artist to add */ public void addItem(Artist a) { synchronized (mArtists) { mArtists.add(a); sortList(); } } /** * Adds an item to the adapter if it's not already there * @param a The artist to add */ public void addItemUnique(Artist a) { synchronized (mArtists) { if (!mArtists.contains(a)) { mArtists.add(a); sortList(); } } } /** * Add all the elements of the collection to the adapter * @param ps The collection of Artist to add */ public void addAll(Collection<Artist> ps) { synchronized (mArtists) { mArtists.addAll(ps); sortList(); } } /** * Add all the elements of the collection to the adapter if they're not already there * @param ps The collection of Artist to add */ public void addAllUnique(Collection<Artist> ps) { synchronized (mArtists) { boolean didChange = false; for (Artist p : ps) { if (!mArtists.contains(p) && p != null) { mArtists.add(p); didChange = true; } } if (didChange) { sortList(); } } } /** * Returns whether or not the adapter contains the provided artist * @param p The artist to check * @return true if the adapter contains the item, false otherwise */ public boolean contains(final Artist p) { synchronized (mArtists) { return mArtists.contains(p); } } /** * Returns the position of the artist in the list * @param a The artist to get the position * @return The index of the item, or -1 if not found */ public int indexOf(final Artist a) { synchronized (mArtists) { return mArtists.indexOf(a); } } /** * {@inheritDoc} */ @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { final LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext()); final View view = inflater.inflate(R.layout.medium_card_one_line, viewGroup, false); final ViewHolder holder = new ViewHolder(view); // Setup album art listener holder.ivCover.setOnArtLoadedListener(mAlbumArtListener); return holder; } /** * {@inheritDoc} */ @Override public void onBindViewHolder(ArtistsAdapter.ViewHolder tag, int position) { // Fill in the fields final Artist artist = getItem(position); // If we're not already displaying the right stuff, reset it and show it tag.artist = artist; tag.position = position; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { tag.ivCover.setTransitionName("grid:image:" + artist.getRef()); tag.tvTitle.setTransitionName("grid:title:" + artist.getRef()); } if (artist.isLoaded() || (artist.getName() != null && !artist.getName().isEmpty())) { tag.tvTitle.setText(artist.getName()); } else { tag.tvTitle.setText(null); } // Set the event listener tag.llRoot.setOnClickListener(mItemClickListener); // Load the artist art final Resources res = tag.llRoot.getResources(); final int defaultColor = res.getColor(R.color.default_album_art_background); tag.llRoot.setBackgroundColor(defaultColor); tag.itemColor = defaultColor; if (artist.getName() != null) { tag.ivCover.loadArtForArtist(artist); } } /** * {@inheritDoc} */ @Override public int getItemCount() { synchronized (mArtists) { return mArtists.size(); } } /** * Returns the item at the provided position * @param position The position of the item * @return The {@link com.fastbootmobile.encore.model.Artist} at the provided position */ public Artist getItem(int position) { synchronized (mArtists) { return mArtists.get(position); } } }