Added album multi select and fixed some minor bugs.

This commit is contained in:
Karim Abou Zeid 2015-05-24 23:00:46 +02:00
commit 4e3f75d295
13 changed files with 167 additions and 75 deletions

View file

@ -27,11 +27,9 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
protected void toggleChecked(final int position) { protected void toggleChecked(final int position) {
if (cabHolder != null) { if (cabHolder != null) {
openCabIfNecessary(); openCabIfNecessary();
if (position > 0) { I identifier = getIdentifier(position);
I identifier = getIdentifier(position); if (!checked.remove(identifier)) checked.add(identifier);
if (!checked.remove(identifier)) checked.add(identifier); notifyItemChanged(position);
notifyItemChanged(position);
}
if (checked.isEmpty()) cab.finish(); if (checked.isEmpty()) cab.finish();
} }
} }

View file

@ -1,27 +1,39 @@
package com.kabouzeid.gramophone.adapter; package com.kabouzeid.gramophone.adapter;
import android.app.Activity; import android.annotation.TargetApi;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Build;
import android.support.v4.util.Pair; import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette; import android.support.v7.graphics.Palette;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.afollestad.materialdialogs.util.DialogUtils; import com.afollestad.materialdialogs.util.DialogUtils;
import com.kabouzeid.gramophone.App; import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
import com.kabouzeid.gramophone.dialogs.DeleteSongsDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.loader.AlbumLoader; import com.kabouzeid.gramophone.loader.AlbumLoader;
import com.kabouzeid.gramophone.loader.AlbumSongLoader;
import com.kabouzeid.gramophone.model.Album; import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.DataBaseChangedEvent; import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.UIPreferenceChangedEvent; import com.kabouzeid.gramophone.model.UIPreferenceChangedEvent;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity; import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.PreferenceUtils; import com.kabouzeid.gramophone.util.PreferenceUtils;
import com.kabouzeid.gramophone.util.Util;
import com.kabouzeid.gramophone.util.ViewUtil; import com.kabouzeid.gramophone.util.ViewUtil;
import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
@ -29,15 +41,16 @@ import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder> { public class AlbumAdapter extends AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album> {
public static final String TAG = AlbumAdapter.class.getSimpleName(); public static final String TAG = AlbumAdapter.class.getSimpleName();
private final Activity activity; private final AppCompatActivity activity;
private boolean usePalette; private boolean usePalette;
private List<Album> dataSet; private List<Album> dataSet;
@ -53,6 +66,10 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
resetColors(holder.title, holder.artist, holder.footer); resetColors(holder.title, holder.artist, holder.footer);
final boolean isChecked = isChecked(album);
holder.view.setActivated(isChecked);
holder.checkMark.setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE);
holder.title.setText(album.title); holder.title.setText(album.title);
holder.artist.setText(album.artistName); holder.artist.setText(album.artistName);
@ -85,34 +102,90 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
return dataSet.size(); return dataSet.size();
} }
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { @Override
protected Album getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected void onMultipleItemAction(MenuItem menuItem, ArrayList<Album> selection) {
switch (menuItem.getItemId()) {
case R.id.action_delete_from_disk:
DeleteSongsDialog.create(getSongList(selection)).show(activity.getSupportFragmentManager(), "DELETE_SONGS");
break;
case R.id.action_add_to_playlist:
AddToPlaylistDialog.create(getSongList(selection)).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
break;
case R.id.action_add_to_current_playing:
MusicPlayerRemote.enqueue(getSongList(selection));
break;
}
}
private ArrayList<Song> getSongList(List<Album> albums) {
final ArrayList<Song> songs = new ArrayList<>();
for (Album album : albums) {
songs.addAll(AlbumSongLoader.getAlbumSongList(activity, album.id));
}
return songs;
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
final ImageView albumArt; final ImageView albumArt;
final TextView title; final TextView title;
final TextView artist; final TextView artist;
final View footer; final View footer;
final ImageView checkMark;
final View view;
public ViewHolder(View itemView) { public ViewHolder(View itemView) {
super(itemView); super(itemView);
view = itemView;
albumArt = (ImageView) itemView.findViewById(R.id.album_art); albumArt = (ImageView) itemView.findViewById(R.id.album_art);
title = (TextView) itemView.findViewById(R.id.album_title); title = (TextView) itemView.findViewById(R.id.album_title);
artist = (TextView) itemView.findViewById(R.id.album_interpret); artist = (TextView) itemView.findViewById(R.id.album_interpret);
footer = itemView.findViewById(R.id.footer); footer = itemView.findViewById(R.id.footer);
itemView.setOnClickListener(this); checkMark = (ImageView) itemView.findViewById(R.id.check_mark);
view.setOnClickListener(this);
view.setOnLongClickListener(this);
// fixes the ripple starts at the right position
if (Util.isAtLeastLollipop()) {
view.setOnTouchListener(new View.OnTouchListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
((FrameLayout) view.findViewById(R.id.content)).getForeground().setHotspot(motionEvent.getX(), motionEvent.getY());
return false;
}
});
}
} }
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Pair[] albumPairs = new Pair[]{ if (isInQuickSelectMode()) {
Pair.create(albumArt, toggleChecked(getAdapterPosition());
activity.getResources().getString(R.string.transition_album_cover) } else {
)}; Pair[] albumPairs = new Pair[]{
if (activity instanceof AbsFabActivity) Pair.create(albumArt,
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs); activity.getResources().getString(R.string.transition_album_cover)
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).id, albumPairs); )};
if (activity instanceof AbsFabActivity)
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).id, albumPairs);
}
}
@Override
public boolean onLongClick(View view) {
toggleChecked(getAdapterPosition());
return true;
} }
} }
public AlbumAdapter(Activity activity) { public AlbumAdapter(AppCompatActivity activity, CabHolder cabHolder) {
super(cabHolder, R.menu.menu_media_selection);
this.activity = activity; this.activity = activity;
usePalette = PreferenceUtils.getInstance(activity).coloredAlbumFootersEnabled(); usePalette = PreferenceUtils.getInstance(activity).coloredAlbumFootersEnabled();
loadDataSet(); loadDataSet();

View file

@ -184,7 +184,8 @@ public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, S
@Override @Override
public boolean onLongClick(View view) { public boolean onLongClick(View view) {
toggleChecked(getAdapterPosition()); if (getItemViewType() == SONG)
toggleChecked(getAdapterPosition());
return true; return true;
} }
} }

View file

@ -559,7 +559,7 @@ public class MainActivity extends AbsFabActivity
@Override @Override
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) { public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
if (cab != null) cab.finish(); if (cab != null && cab.isActive()) cab.finish();
cab = new MaterialCab(this, R.id.cab_stub) cab = new MaterialCab(this, R.id.cab_stub)
.setMenu(menu) .setMenu(menu)
.setBackgroundColor(PreferenceUtils.getInstance(this).getThemeColorPrimary()) .setBackgroundColor(PreferenceUtils.getInstance(this).getThemeColorPrimary())

View file

@ -30,7 +30,7 @@ public class AlbumViewFragment extends AbsMainActivityRecyclerViewFragment {
@Override @Override
protected RecyclerView.Adapter createAdapter() { protected RecyclerView.Adapter createAdapter() {
return new AlbumAdapter(getActivity()); return new AlbumAdapter(getMainActivity(), getMainActivity());
} }
public void setColumns(int columns) { public void setColumns(int columns) {

View file

@ -22,6 +22,6 @@ public class ArtistViewFragment extends AbsMainActivityRecyclerViewFragment {
@Override @Override
protected RecyclerView.Adapter createAdapter() { protected RecyclerView.Adapter createAdapter() {
return new ArtistAdapter(getActivity()); return new ArtistAdapter(getMainActivity());
} }
} }

View file

@ -2,7 +2,6 @@ package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
@ -41,7 +40,7 @@ public class PlaylistViewFragment extends AbsMainActivityRecyclerViewFragment {
@Override @Override
protected RecyclerView.Adapter createAdapter() { protected RecyclerView.Adapter createAdapter() {
PlaylistAdapter adapter = new PlaylistAdapter((AppCompatActivity) getActivity()); PlaylistAdapter adapter = new PlaylistAdapter(getMainActivity());
View v = getView(); View v = getView();
if (v != null) { if (v != null) {
v.findViewById(android.R.id.empty).setVisibility( v.findViewById(android.R.id.empty).setVisibility(

View file

@ -1,6 +1,5 @@
package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments; package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
@ -26,6 +25,6 @@ public class SongViewFragment extends AbsMainActivityRecyclerViewFragment {
@Override @Override
protected RecyclerView.Adapter createAdapter() { protected RecyclerView.Adapter createAdapter() {
return new SongAdapter((AppCompatActivity) getActivity(), getMainActivity()); return new SongAdapter(getMainActivity(), getMainActivity());
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1,56 +1,75 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" 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:layout_margin="1dp">
android:layout_margin="2dp"
android:foreground="?rect_selector"
app:elevation="3dp">
<LinearLayout <FrameLayout
android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:gravity="center" android:foreground="?rect_selector">
android:orientation="vertical"
tools:ignore="UnusedAttribute,UselessParent">
<com.kabouzeid.gramophone.views.SquareImageView
android:id="@+id/album_art"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:transitionName="@string/transition_album_cover" />
<LinearLayout <LinearLayout
android:id="@+id/footer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:background="?default_bar_color" android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp" tools:ignore="UnusedAttribute,UselessParent">
android:transitionName="@string/transition_album_text">
<TextView <com.kabouzeid.gramophone.views.SquareImageView
android:id="@+id/album_title" android:id="@+id/album_art"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:fontFamily="sans-serif-medium" android:scaleType="centerCrop"
android:singleLine="true" android:src="@drawable/default_album_art"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" android:transitionName="@string/transition_album_cover" />
android:textColor="?title_text_color" />
<TextView
android:id="@+id/album_interpret" <LinearLayout
android:layout_width="wrap_content" android:id="@+id/footer"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:fontFamily="sans-serif" android:layout_height="68dp"
android:singleLine="true" android:background="?default_bar_color"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:gravity="center_vertical"
android:textColor="?caption_text_color" /> android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:transitionName="@string/transition_album_text">
<TextView
android:id="@+id/album_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="?title_text_color" />
<TextView
android:id="@+id/album_interpret"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="?caption_text_color" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </FrameLayout>
<ImageView
android:id="@+id/check_mark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingBottom="68dp"
android:src="@drawable/ic_check_white_96dp"
android:tint="?check_mark_color"
android:visibility="invisible" />
</FrameLayout> </FrameLayout>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="72dp" android:layout_height="72dp"
android:foreground="?rect_selector"> android:foreground="?rect_selector">
<LinearLayout <LinearLayout
@ -11,7 +11,7 @@
android:descendantFocusability="blocksDescendants" android:descendantFocusability="blocksDescendants"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingStart="16dp"> android:paddingRight="16dp">
<com.kabouzeid.gramophone.views.SquareImageView <com.kabouzeid.gramophone.views.SquareImageView
android:id="@+id/album_art" android:id="@+id/album_art"
@ -53,8 +53,8 @@
android:id="@+id/menu" android:id="@+id/menu"
style="@style/OverFlowButton" style="@style/OverFlowButton"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp" android:layout_marginRight="2dp"
android:layout_marginEnd="2dp"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
</LinearLayout> </LinearLayout>

View file

@ -18,6 +18,7 @@
<attr name="drawable_color_enabled" format="color" /> <attr name="drawable_color_enabled" format="color" />
<attr name="themed_drawable_color" format="color" /> <attr name="themed_drawable_color" format="color" />
<attr name="check_mark_color" format="color" />
<attr name="default_bar_color" format="color" /> <attr name="default_bar_color" format="color" />
<attr name="card_color" format="color" /> <attr name="card_color" format="color" />

View file

@ -25,6 +25,7 @@
<item name="nav_drawer_icon_color">#fff</item> <item name="nav_drawer_icon_color">#fff</item>
<item name="themed_drawable_color">@color/materialmusic_dark_themed_drawable_color</item> <item name="themed_drawable_color">@color/materialmusic_dark_themed_drawable_color</item>
<item name="check_mark_color">@color/grey_900</item>
<item name="default_bar_color">@color/materialmusic_dark_default_bar_color</item> <item name="default_bar_color">@color/materialmusic_dark_default_bar_color</item>
<item name="card_color">@color/materialmusic_dark_default_bar_color</item> <item name="card_color">@color/materialmusic_dark_default_bar_color</item>
@ -56,6 +57,7 @@
<item name="nav_drawer_icon_color">#000</item> <item name="nav_drawer_icon_color">#000</item>
<item name="themed_drawable_color">@color/materialmusic_themed_drawable_color</item> <item name="themed_drawable_color">@color/materialmusic_themed_drawable_color</item>
<item name="check_mark_color">@color/white</item>
<item name="default_bar_color">@color/materialmusic_default_bar_color</item> <item name="default_bar_color">@color/materialmusic_default_bar_color</item>
<item name="card_color">@color/white</item> <item name="card_color">@color/white</item>