From 0e5adaf361b802aecdda32c7c262afbf70ad7e61 Mon Sep 17 00:00:00 2001 From: Marco Hunsicker <31240866+doompadee@users.noreply.github.com> Date: Sat, 23 Dec 2017 17:10:51 +0100 Subject: [PATCH] Make library categories configurable --- .../adapter/MusicLibraryPagerAdapter.java | 119 +++++++++++++----- .../kabouzeid/gramophone/model/Category.java | 65 ++++++++++ .../mainactivity/library/LibraryFragment.java | 22 +++- .../gramophone/util/PreferenceUtil.java | 60 +++++++++ 4 files changed, 235 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/model/Category.java diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/MusicLibraryPagerAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/MusicLibraryPagerAdapter.java index ee292b4f..39763fda 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/MusicLibraryPagerAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/MusicLibraryPagerAdapter.java @@ -10,14 +10,17 @@ import android.util.SparseArray; import android.view.ViewGroup; import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.model.Category; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.AlbumsFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.ArtistsFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.GenresFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.PlaylistsFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.SongsFragment; +import com.kabouzeid.gramophone.util.PreferenceUtil; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -30,33 +33,29 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter { @NonNull private final Context mContext; - @NonNull - private final String[] titles; - public MusicLibraryPagerAdapter(@NonNull final Context context, final FragmentManager fragmentManager) { super(fragmentManager); mContext = context; - titles = new String[]{ - context.getResources().getString(R.string.songs), - context.getResources().getString(R.string.albums), - context.getResources().getString(R.string.artists), - context.getResources().getString(R.string.genres), - context.getResources().getString(R.string.playlists) - }; - final MusicFragments[] fragments = MusicFragments.values(); - for (final MusicLibraryPagerAdapter.MusicFragments fragment : fragments) { - add(fragment.getFragmentClass(), null); - } + setCategories(PreferenceUtil.getInstance(context).getLibraryCategories()); } - @SuppressWarnings("synthetic-access") - public void add(@NonNull final Class className, final Bundle params) { - final Holder mHolder = new Holder(); - mHolder.mClassName = className.getName(); - mHolder.mParams = params; + public void setCategories(@NonNull ArrayList categories) { + mHolderList.clear(); - final int mPosition = mHolderList.size(); - mHolderList.add(mPosition, mHolder); + for (int i = 0, size = categories.size(); i < size; i++) { + Category category = categories.get(i); + if (category.visible) { + MusicFragments fragment = MusicFragments.valueOf(category.id.toString()); + Holder holder = new Holder(); + holder.mClassName = fragment.getFragmentClass().getName(); + holder.title = mContext.getResources() + .getString(fragment.getResourceKey()) + .toUpperCase(Locale.getDefault()); + mHolderList.add(holder); + } + } + + alignCache(); notifyDataSetChanged(); } @@ -68,6 +67,23 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter { return getItem(position); } + @Override + public int getItemPosition(@NonNull Object fragment) { + for (int i = 0, size = mHolderList.size(); i < size; i++) { + Holder holder = mHolderList.get(i); + if (holder.mClassName.equals(fragment.getClass().getName())) { + return i; + } + } + return POSITION_NONE; + } + + @Override + public long getItemId(int position) { + // as fragment position is not fixed, we can't use position as id + return MusicFragments.of(getFragment(position).getClass()).ordinal(); + } + @NonNull @Override public Object instantiateItem(@NonNull final ViewGroup container, final int position) { @@ -104,30 +120,75 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter { @NonNull @Override public CharSequence getPageTitle(final int position) { - return titles[position] - .toUpperCase(Locale.getDefault()); + return mHolderList.get(position).title; + } + + /** + * Aligns the fragment cache with the current category layout. + */ + private void alignCache() { + if (mFragmentArray.size() == 0) return; + + HashMap> mappings = new HashMap<>(mFragmentArray.size()); + + for (int i = 0, size = mFragmentArray.size(); i < size; i++) { + WeakReference ref = mFragmentArray.valueAt(i); + Fragment fragment = ref.get(); + if (fragment != null) { + mappings.put(fragment.getClass().getName(), ref); + } + } + for (int i = 0, size = mHolderList.size(); i < size; i++) { + WeakReference ref = mappings.get(mHolderList.get(i).mClassName); + if (ref != null) { + mFragmentArray.put(i, ref); + } else { + mFragmentArray.remove(i); + } + } } public enum MusicFragments { - SONG(SongsFragment.class), - ALBUM(AlbumsFragment.class), - ARTIST(ArtistsFragment.class), - GENRES(GenresFragment.class), - PLAYLIST(PlaylistsFragment.class); + SONGS(SongsFragment.class, R.string.songs), + ALBUMS(AlbumsFragment.class, R.string.albums), + ARTISTS(ArtistsFragment.class, R.string.artists), + GENRES(GenresFragment.class, R.string.genres), + PLAYLISTS(PlaylistsFragment.class, R.string.playlists); private final Class mFragmentClass; + private final int key; - MusicFragments(final Class fragmentClass) { + MusicFragments(final Class fragmentClass, int key) { mFragmentClass = fragmentClass; + this.key = key; } public Class getFragmentClass() { return mFragmentClass; } + + public int getResourceKey() { + return key; + } + + public static MusicFragments of(Class cl) { + MusicFragments[] fragments = All.FRAGMENTS; + for (int i = 0; i < fragments.length; i++) { + if (cl.equals(fragments[i].mFragmentClass)) + return fragments[i]; + } + + throw new IllegalArgumentException("Unknown music fragment " + cl); + } + + private static class All { + public static final MusicFragments[] FRAGMENTS = values(); + } } private final static class Holder { String mClassName; Bundle mParams; + String title; } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/model/Category.java b/app/src/main/java/com/kabouzeid/gramophone/model/Category.java new file mode 100644 index 00000000..87013376 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/model/Category.java @@ -0,0 +1,65 @@ +package com.kabouzeid.gramophone.model; + +import com.kabouzeid.gramophone.R; + +import com.google.gson.annotations.SerializedName; + +public class Category { + @SerializedName("id") + public Id id; + + @SerializedName("index") + public int index; + + @SerializedName("checkBox") + public boolean visible; + + public Category(Category category) { + this.id = category.id; + this.visible = category.visible; + this.index = index; + } + + public Category(Id id, boolean visible, int index) { + this.id = id; + this.visible = visible; + this.index = index; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Category category = (Category) o; + + return id == category.id; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + id.hashCode(); + return result; + } + + public String toString() + { + return "{id:"+id + ", pos:"+ index + ", vis=" + visible + "}"; + } + + public static enum Id + { + SONGS(R.string.songs), + ALBUMS(R.string.albums), + ARTISTS(R.string.artists), + GENRES(R.string.genres), + PLAYLISTS(R.string.playlists); + + public final int key; + + private Id(int key) { + this.key = key; + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/library/LibraryFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/library/LibraryFragment.java index dddfd8e8..536102ee 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/library/LibraryFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/library/LibraryFragment.java @@ -3,6 +3,7 @@ package com.kabouzeid.gramophone.ui.fragments.mainactivity.library; import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -34,6 +35,7 @@ import com.kabouzeid.gramophone.ui.activities.MainActivity; import com.kabouzeid.gramophone.ui.activities.SearchActivity; import com.kabouzeid.gramophone.ui.fragments.mainactivity.AbsMainActivityFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.AbsLibraryPagerRecyclerViewCustomGridSizeFragment; +import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.PlaylistsFragment; import com.kabouzeid.gramophone.util.PhonographColorUtil; import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.Util; @@ -42,7 +44,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.Unbinder; -public class LibraryFragment extends AbsMainActivityFragment implements CabHolder, MainActivity.MainActivityFragmentCallbacks, ViewPager.OnPageChangeListener { +public class LibraryFragment extends AbsMainActivityFragment implements CabHolder, MainActivity.MainActivityFragmentCallbacks, ViewPager.OnPageChangeListener, SharedPreferences.OnSharedPreferenceChangeListener { public static final String TAG = LibraryFragment.class.getSimpleName(); private Unbinder unbinder; @@ -75,6 +77,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde @Override public void onDestroyView() { + PreferenceUtil.getInstance(getActivity()).unregisterOnSharedPreferenceChangedListener(this); super.onDestroyView(); pager.removeOnPageChangeListener(this); unbinder.unbind(); @@ -82,6 +85,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + PreferenceUtil.getInstance(getActivity()).registerOnSharedPreferenceChangedListener(this); setStatusbarColorAuto(view); getMainActivity().setNavigationbarColorAuto(); getMainActivity().setTaskDescriptionColorAuto(); @@ -90,6 +94,20 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde setUpViewPager(); } + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + if (PreferenceUtil.LIBRARY_CATEGORIES.equals(key)) { + Fragment current = getCurrentFragment(); + pagerAdapter.setCategories(PreferenceUtil.getInstance(getActivity()).getLibraryCategories()); + pager.setOffscreenPageLimit(pagerAdapter.getCount() - 1); + int position = pagerAdapter.getItemPosition(current); + pager.setCurrentItem(position > -1 ? position : 0); + + // hide the tab bar with single tab + tabs.setVisibility(pagerAdapter.getCount() == 1 ? View.GONE : View.VISIBLE); + } + } + private void setUpToolbar() { int primaryColor = ThemeStore.primaryColor(getActivity()); appbar.setBackgroundColor(primaryColor); @@ -125,7 +143,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde } private boolean isPlaylistPage() { - return pager.getCurrentItem() == MusicLibraryPagerAdapter.MusicFragments.PLAYLIST.ordinal(); + return getCurrentFragment() instanceof PlaylistsFragment; } @NonNull diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java index 497f371a..18af25a2 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java @@ -9,10 +9,17 @@ import android.support.annotation.StyleRes; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.helper.SortOrder; +import com.kabouzeid.gramophone.model.Category; import com.kabouzeid.gramophone.ui.fragments.mainactivity.folders.FoldersFragment; import com.kabouzeid.gramophone.ui.fragments.player.NowPlayingScreen; import java.io.File; +import java.util.Collections; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import com.google.gson.Gson; public final class PreferenceUtil { public static final String GENERAL_THEME = "general_theme"; @@ -74,6 +81,8 @@ public final class PreferenceUtil { public static final String INITIALIZED_BLACKLIST = "initialized_blacklist"; + public static final String LIBRARY_CATEGORIES = "library_categories"; + private static PreferenceUtil sInstance; private final SharedPreferences mPreferences; @@ -426,4 +435,55 @@ public final class PreferenceUtil { public final boolean initializedBlacklist() { return mPreferences.getBoolean(INITIALIZED_BLACKLIST, false); } + + public void setLibraryCategories(ArrayList categories) { + Gson gson = new Gson(); + + Set data = new HashSet<>(categories.size()); + + for (int i = 0, size = categories.size(); i < size; i++) { + Category category = categories.get(i); + category.index = i; + data.add(gson.toJson(category)); + } + + SharedPreferences.Editor editor = mPreferences.edit(); + editor.putStringSet(LIBRARY_CATEGORIES, data); + editor.commit(); + } + + public ArrayList getLibraryCategories() { + Set data = mPreferences.getStringSet(LIBRARY_CATEGORIES, null); + if (data != null) { + Gson gson = new Gson(); + ArrayList result = new ArrayList<>(Collections.nCopies(data.size(), (Category) null)); + + for (String json : data) { + Category category = gson.fromJson(json, Category.class); + result.set(category.index, category); + } + + return result; + } + + return LibraryCategories.DEFAULTS; + } + + public ArrayList getDefaultLibraryCategories() { + return LibraryCategories.DEFAULTS; + } + + private static class LibraryCategories { + public final static ArrayList DEFAULTS = getDefaults(); + + private static ArrayList getDefaults() { + ArrayList result = new ArrayList<>(); + result.add(new Category(Category.Id.SONGS, true, 0)); + result.add(new Category(Category.Id.ALBUMS, true, 1)); + result.add(new Category(Category.Id.ARTISTS, true, 2)); + result.add(new Category(Category.Id.GENRES, true, 3)); + result.add(new Category(Category.Id.PLAYLISTS, true, 4)); + return result; + } + } }