Merge pull request #387 from doompadee/library-categories
Make Library categories configurable
This commit is contained in:
commit
a892ffb75f
15 changed files with 516 additions and 30 deletions
|
|
@ -125,6 +125,7 @@ dependencies {
|
||||||
implementation('com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.11.0@aar') {
|
implementation('com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.11.0@aar') {
|
||||||
transitive = true
|
transitive = true
|
||||||
}
|
}
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.2'
|
||||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.8.0'
|
implementation 'com.crashlytics.sdk.android:crashlytics:2.8.0'
|
||||||
implementation('com.crashlytics.sdk.android:answers:1.3.13@aar') {
|
implementation('com.crashlytics.sdk.android:answers:1.3.13@aar') {
|
||||||
transitive = true
|
transitive = true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
package com.kabouzeid.gramophone.adapter;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.model.CategoryInfo;
|
||||||
|
import com.kabouzeid.gramophone.util.SwipeAndDragHelper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class CategoryInfoAdapter extends RecyclerView.Adapter<CategoryInfoAdapter.ViewHolder> implements SwipeAndDragHelper.ActionCompletionContract {
|
||||||
|
private ArrayList<CategoryInfo> categoryInfos;
|
||||||
|
private ItemTouchHelper touchHelper;
|
||||||
|
|
||||||
|
public CategoryInfoAdapter(ArrayList<CategoryInfo> categoryInfos) {
|
||||||
|
this.categoryInfos = categoryInfos;
|
||||||
|
SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(this);
|
||||||
|
touchHelper = new ItemTouchHelper(swipeAndDragHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CategoryInfoAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.preference_dialog_library_categories_listitem, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(CategoryInfoAdapter.ViewHolder holder, int position) {
|
||||||
|
CategoryInfo categoryInfo = categoryInfos.get(position);
|
||||||
|
|
||||||
|
holder.checkBox.setChecked(categoryInfo.visible);
|
||||||
|
holder.title.setText(holder.title.getResources().getString(categoryInfo.category.stringRes));
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (!(categoryInfo.visible && isLastCheckedCategory(categoryInfo))) {
|
||||||
|
categoryInfo.visible = !categoryInfo.visible;
|
||||||
|
holder.checkBox.setChecked(categoryInfo.visible);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.dragView.setOnTouchListener((view, event) -> {
|
||||||
|
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
|
touchHelper.startDrag(holder);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return categoryInfos.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setCategoryInfos(ArrayList<CategoryInfo> categoryInfos) {
|
||||||
|
this.categoryInfos = categoryInfos;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewMoved(int oldPosition, int newPosition) {
|
||||||
|
CategoryInfo categoryInfo = categoryInfos.get(oldPosition);
|
||||||
|
categoryInfos.remove(oldPosition);
|
||||||
|
categoryInfos.add(newPosition, categoryInfo);
|
||||||
|
notifyItemMoved(oldPosition, newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attachToRecyclerView(RecyclerView recyclerView) {
|
||||||
|
touchHelper.attachToRecyclerView(recyclerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<CategoryInfo> getCategoryInfos() {
|
||||||
|
return categoryInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLastCheckedCategory(CategoryInfo categoryInfo) {
|
||||||
|
if (categoryInfo.visible) {
|
||||||
|
for (CategoryInfo c : categoryInfos) {
|
||||||
|
if (c != categoryInfo && c.visible) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
public CheckBox checkBox;
|
||||||
|
public TextView title;
|
||||||
|
public View dragView;
|
||||||
|
|
||||||
|
public ViewHolder(View view) {
|
||||||
|
super(view);
|
||||||
|
checkBox = view.findViewById(R.id.checkbox);
|
||||||
|
title = view.findViewById(R.id.title);
|
||||||
|
dragView = view.findViewById(R.id.drag_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -9,15 +9,17 @@ import android.support.v4.app.FragmentPagerAdapter;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.model.CategoryInfo;
|
||||||
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.AlbumsFragment;
|
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.ArtistsFragment;
|
||||||
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.GenresFragment;
|
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.PlaylistsFragment;
|
||||||
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.SongsFragment;
|
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.SongsFragment;
|
||||||
|
import com.kabouzeid.gramophone.util.PreferenceUtil;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
|
@ -30,33 +32,28 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final String[] titles;
|
|
||||||
|
|
||||||
public MusicLibraryPagerAdapter(@NonNull final Context context, final FragmentManager fragmentManager) {
|
public MusicLibraryPagerAdapter(@NonNull final Context context, final FragmentManager fragmentManager) {
|
||||||
super(fragmentManager);
|
super(fragmentManager);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
titles = new String[]{
|
setCategoryInfos(PreferenceUtil.getInstance(context).getLibraryCategoryInfos());
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("synthetic-access")
|
public void setCategoryInfos(@NonNull ArrayList<CategoryInfo> categoryInfos) {
|
||||||
public void add(@NonNull final Class<? extends Fragment> className, final Bundle params) {
|
mHolderList.clear();
|
||||||
final Holder mHolder = new Holder();
|
|
||||||
mHolder.mClassName = className.getName();
|
|
||||||
mHolder.mParams = params;
|
|
||||||
|
|
||||||
final int mPosition = mHolderList.size();
|
for (CategoryInfo categoryInfo : categoryInfos) {
|
||||||
mHolderList.add(mPosition, mHolder);
|
if (categoryInfo.visible) {
|
||||||
|
MusicFragments fragment = MusicFragments.valueOf(categoryInfo.category.toString());
|
||||||
|
Holder holder = new Holder();
|
||||||
|
holder.mClassName = fragment.getFragmentClass().getName();
|
||||||
|
holder.title = mContext.getResources()
|
||||||
|
.getString(categoryInfo.category.stringRes)
|
||||||
|
.toUpperCase(Locale.getDefault());
|
||||||
|
mHolderList.add(holder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alignCache();
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,6 +65,23 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
|
||||||
return getItem(position);
|
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
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
|
public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
|
||||||
|
|
@ -104,16 +118,40 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getPageTitle(final int position) {
|
public CharSequence getPageTitle(final int position) {
|
||||||
return titles[position]
|
return mHolderList.get(position).title;
|
||||||
.toUpperCase(Locale.getDefault());
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aligns the fragment cache with the current category layout.
|
||||||
|
*/
|
||||||
|
private void alignCache() {
|
||||||
|
if (mFragmentArray.size() == 0) return;
|
||||||
|
|
||||||
|
HashMap<String, WeakReference<Fragment>> mappings = new HashMap<>(mFragmentArray.size());
|
||||||
|
|
||||||
|
for (int i = 0, size = mFragmentArray.size(); i < size; i++) {
|
||||||
|
WeakReference<Fragment> 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<Fragment> ref = mappings.get(mHolderList.get(i).mClassName);
|
||||||
|
if (ref != null) {
|
||||||
|
mFragmentArray.put(i, ref);
|
||||||
|
} else {
|
||||||
|
mFragmentArray.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MusicFragments {
|
public enum MusicFragments {
|
||||||
SONG(SongsFragment.class),
|
SONGS(SongsFragment.class),
|
||||||
ALBUM(AlbumsFragment.class),
|
ALBUMS(AlbumsFragment.class),
|
||||||
ARTIST(ArtistsFragment.class),
|
ARTISTS(ArtistsFragment.class),
|
||||||
GENRES(GenresFragment.class),
|
GENRES(GenresFragment.class),
|
||||||
PLAYLIST(PlaylistsFragment.class);
|
PLAYLISTS(PlaylistsFragment.class);
|
||||||
|
|
||||||
private final Class<? extends Fragment> mFragmentClass;
|
private final Class<? extends Fragment> mFragmentClass;
|
||||||
|
|
||||||
|
|
@ -124,10 +162,25 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
|
||||||
public Class<? extends Fragment> getFragmentClass() {
|
public Class<? extends Fragment> getFragmentClass() {
|
||||||
return mFragmentClass;
|
return mFragmentClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
private final static class Holder {
|
||||||
String mClassName;
|
String mClassName;
|
||||||
Bundle mParams;
|
Bundle mParams;
|
||||||
|
String title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.kabouzeid.gramophone.model;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
|
||||||
|
public class CategoryInfo {
|
||||||
|
public Category category;
|
||||||
|
public boolean visible;
|
||||||
|
|
||||||
|
public CategoryInfo(Category category, boolean visible) {
|
||||||
|
this.category = category;
|
||||||
|
this.visible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Category {
|
||||||
|
SONGS(R.string.songs),
|
||||||
|
ALBUMS(R.string.albums),
|
||||||
|
ARTISTS(R.string.artists),
|
||||||
|
GENRES(R.string.genres),
|
||||||
|
PLAYLISTS(R.string.playlists);
|
||||||
|
|
||||||
|
public final int stringRes;
|
||||||
|
|
||||||
|
Category(int stringRes) {
|
||||||
|
this.stringRes = stringRes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.kabouzeid.gramophone.preferences;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import com.kabouzeid.appthemehelper.common.prefs.supportv7.ATEDialogPreference;
|
||||||
|
|
||||||
|
public class LibraryPreference extends ATEDialogPreference {
|
||||||
|
public LibraryPreference(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LibraryPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.kabouzeid.gramophone.preferences;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.adapter.CategoryInfoAdapter;
|
||||||
|
import com.kabouzeid.gramophone.model.CategoryInfo;
|
||||||
|
import com.kabouzeid.gramophone.util.PreferenceUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
public class LibraryPreferenceDialog extends DialogFragment {
|
||||||
|
public static LibraryPreferenceDialog newInstance() {
|
||||||
|
return new LibraryPreferenceDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
View view = getActivity().getLayoutInflater().inflate(R.layout.preference_dialog_library_categories, null);
|
||||||
|
|
||||||
|
CategoryInfoAdapter adapter = new CategoryInfoAdapter(PreferenceUtil.getInstance(getContext()).getLibraryCategoryInfos());
|
||||||
|
|
||||||
|
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
adapter.attachToRecyclerView(recyclerView);
|
||||||
|
|
||||||
|
return new MaterialDialog.Builder(getContext())
|
||||||
|
.title(R.string.library_categories)
|
||||||
|
.customView(view, false)
|
||||||
|
.positiveText(android.R.string.ok)
|
||||||
|
.negativeText(android.R.string.cancel)
|
||||||
|
.neutralText(R.string.reset_action)
|
||||||
|
.autoDismiss(false)
|
||||||
|
.onNeutral((dialog, action) -> adapter.setCategoryInfos(PreferenceUtil.getInstance(getContext()).getDefaultLibraryCategoryInfos()))
|
||||||
|
.onNegative((dialog, action) -> dismiss())
|
||||||
|
.onPositive((dialog, action) -> {
|
||||||
|
updateCategories(adapter.getCategoryInfos());
|
||||||
|
dismiss();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCategories(ArrayList<CategoryInfo> categories) {
|
||||||
|
if (getSelected(categories) == 0) return;
|
||||||
|
|
||||||
|
PreferenceUtil.getInstance(getContext()).setLibraryCategoryInfos(categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelected(ArrayList<CategoryInfo> categories) {
|
||||||
|
int selected = 0;
|
||||||
|
for (CategoryInfo categoryInfo : categories) {
|
||||||
|
if (categoryInfo.visible)
|
||||||
|
selected++;
|
||||||
|
}
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,8 @@ import com.kabouzeid.gramophone.appshortcuts.DynamicShortcutManager;
|
||||||
import com.kabouzeid.gramophone.misc.NonProAllowedColors;
|
import com.kabouzeid.gramophone.misc.NonProAllowedColors;
|
||||||
import com.kabouzeid.gramophone.preferences.BlacklistPreference;
|
import com.kabouzeid.gramophone.preferences.BlacklistPreference;
|
||||||
import com.kabouzeid.gramophone.preferences.BlacklistPreferenceDialog;
|
import com.kabouzeid.gramophone.preferences.BlacklistPreferenceDialog;
|
||||||
|
import com.kabouzeid.gramophone.preferences.LibraryPreference;
|
||||||
|
import com.kabouzeid.gramophone.preferences.LibraryPreferenceDialog;
|
||||||
import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreference;
|
import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreference;
|
||||||
import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreferenceDialog;
|
import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreferenceDialog;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity;
|
||||||
|
|
@ -167,6 +169,8 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia
|
||||||
return NowPlayingScreenPreferenceDialog.newInstance();
|
return NowPlayingScreenPreferenceDialog.newInstance();
|
||||||
} else if (preference instanceof BlacklistPreference) {
|
} else if (preference instanceof BlacklistPreference) {
|
||||||
return BlacklistPreferenceDialog.newInstance();
|
return BlacklistPreferenceDialog.newInstance();
|
||||||
|
} else if (preference instanceof LibraryPreference) {
|
||||||
|
return LibraryPreferenceDialog.newInstance();
|
||||||
}
|
}
|
||||||
return super.onCreatePreferenceDialog(preference);
|
return super.onCreatePreferenceDialog(preference);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.kabouzeid.gramophone.ui.fragments.mainactivity.library;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
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.activities.SearchActivity;
|
||||||
import com.kabouzeid.gramophone.ui.fragments.mainactivity.AbsMainActivityFragment;
|
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.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
|
||||||
|
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.pager.PlaylistsFragment;
|
||||||
import com.kabouzeid.gramophone.util.PhonographColorUtil;
|
import com.kabouzeid.gramophone.util.PhonographColorUtil;
|
||||||
import com.kabouzeid.gramophone.util.PreferenceUtil;
|
import com.kabouzeid.gramophone.util.PreferenceUtil;
|
||||||
import com.kabouzeid.gramophone.util.Util;
|
import com.kabouzeid.gramophone.util.Util;
|
||||||
|
|
@ -42,7 +44,7 @@ import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.Unbinder;
|
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();
|
public static final String TAG = LibraryFragment.class.getSimpleName();
|
||||||
|
|
||||||
private Unbinder unbinder;
|
private Unbinder unbinder;
|
||||||
|
|
@ -75,6 +77,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
|
PreferenceUtil.getInstance(getActivity()).unregisterOnSharedPreferenceChangedListener(this);
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
pager.removeOnPageChangeListener(this);
|
pager.removeOnPageChangeListener(this);
|
||||||
unbinder.unbind();
|
unbinder.unbind();
|
||||||
|
|
@ -82,6 +85,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
PreferenceUtil.getInstance(getActivity()).registerOnSharedPreferenceChangedListener(this);
|
||||||
setStatusbarColorAuto(view);
|
setStatusbarColorAuto(view);
|
||||||
getMainActivity().setNavigationbarColorAuto();
|
getMainActivity().setNavigationbarColorAuto();
|
||||||
getMainActivity().setTaskDescriptionColorAuto();
|
getMainActivity().setTaskDescriptionColorAuto();
|
||||||
|
|
@ -90,6 +94,20 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
|
||||||
setUpViewPager();
|
setUpViewPager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
|
if (PreferenceUtil.LIBRARY_CATEGORIES.equals(key)) {
|
||||||
|
Fragment current = getCurrentFragment();
|
||||||
|
pagerAdapter.setCategoryInfos(PreferenceUtil.getInstance(getActivity()).getLibraryCategoryInfos());
|
||||||
|
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() {
|
private void setUpToolbar() {
|
||||||
int primaryColor = ThemeStore.primaryColor(getActivity());
|
int primaryColor = ThemeStore.primaryColor(getActivity());
|
||||||
appbar.setBackgroundColor(primaryColor);
|
appbar.setBackgroundColor(primaryColor);
|
||||||
|
|
@ -125,7 +143,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPlaylistPage() {
|
private boolean isPlaylistPage() {
|
||||||
return pager.getCurrentItem() == MusicLibraryPagerAdapter.MusicFragments.PLAYLIST.ordinal();
|
return getCurrentFragment() instanceof PlaylistsFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,18 @@ import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.StyleRes;
|
import android.support.annotation.StyleRes;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.helper.SortOrder;
|
import com.kabouzeid.gramophone.helper.SortOrder;
|
||||||
|
import com.kabouzeid.gramophone.model.CategoryInfo;
|
||||||
import com.kabouzeid.gramophone.ui.fragments.mainactivity.folders.FoldersFragment;
|
import com.kabouzeid.gramophone.ui.fragments.mainactivity.folders.FoldersFragment;
|
||||||
import com.kabouzeid.gramophone.ui.fragments.player.NowPlayingScreen;
|
import com.kabouzeid.gramophone.ui.fragments.player.NowPlayingScreen;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public final class PreferenceUtil {
|
public final class PreferenceUtil {
|
||||||
public static final String GENERAL_THEME = "general_theme";
|
public static final String GENERAL_THEME = "general_theme";
|
||||||
|
|
@ -74,6 +80,8 @@ public final class PreferenceUtil {
|
||||||
|
|
||||||
public static final String INITIALIZED_BLACKLIST = "initialized_blacklist";
|
public static final String INITIALIZED_BLACKLIST = "initialized_blacklist";
|
||||||
|
|
||||||
|
public static final String LIBRARY_CATEGORIES = "library_categories";
|
||||||
|
|
||||||
private static PreferenceUtil sInstance;
|
private static PreferenceUtil sInstance;
|
||||||
|
|
||||||
private final SharedPreferences mPreferences;
|
private final SharedPreferences mPreferences;
|
||||||
|
|
@ -426,4 +434,41 @@ public final class PreferenceUtil {
|
||||||
public final boolean initializedBlacklist() {
|
public final boolean initializedBlacklist() {
|
||||||
return mPreferences.getBoolean(INITIALIZED_BLACKLIST, false);
|
return mPreferences.getBoolean(INITIALIZED_BLACKLIST, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLibraryCategoryInfos(ArrayList<CategoryInfo> categories) {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
Type collectionType = new TypeToken<ArrayList<CategoryInfo>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
editor.putString(LIBRARY_CATEGORIES, gson.toJson(categories, collectionType));
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<CategoryInfo> getLibraryCategoryInfos() {
|
||||||
|
String data = mPreferences.getString(LIBRARY_CATEGORIES, null);
|
||||||
|
if (data != null) {
|
||||||
|
Gson gson = new Gson();
|
||||||
|
Type collectionType = new TypeToken<ArrayList<CategoryInfo>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return gson.fromJson(data, collectionType);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDefaultLibraryCategoryInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<CategoryInfo> getDefaultLibraryCategoryInfos() {
|
||||||
|
ArrayList<CategoryInfo> defaultCategoryInfos = new ArrayList<>(5);
|
||||||
|
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.SONGS, true));
|
||||||
|
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.ALBUMS, true));
|
||||||
|
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.ARTISTS, true));
|
||||||
|
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.GENRES, true));
|
||||||
|
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.PLAYLISTS, true));
|
||||||
|
return defaultCategoryInfos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.kabouzeid.gramophone.util;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||||
|
|
||||||
|
public class SwipeAndDragHelper extends ItemTouchHelper.Callback {
|
||||||
|
|
||||||
|
private ActionCompletionContract contract;
|
||||||
|
|
||||||
|
public SwipeAndDragHelper(ActionCompletionContract contract) {
|
||||||
|
this.contract = contract;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||||
|
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
|
||||||
|
return makeMovementFlags(dragFlags, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
|
||||||
|
contract.onViewMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLongPressDragEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChildDraw(Canvas c,
|
||||||
|
RecyclerView recyclerView,
|
||||||
|
RecyclerView.ViewHolder viewHolder,
|
||||||
|
float dX,
|
||||||
|
float dY,
|
||||||
|
int actionState,
|
||||||
|
boolean isCurrentlyActive) {
|
||||||
|
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
|
||||||
|
float alpha = 1 - (Math.abs(dX) / recyclerView.getWidth());
|
||||||
|
viewHolder.itemView.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ActionCompletionContract {
|
||||||
|
void onViewMoved(int oldPosition, int newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.constraint.ConstraintLayout 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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout 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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:descendantFocusability="blocksDescendants"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?attr/rectSelector"
|
||||||
|
android:minHeight="@dimen/md_listitem_height"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingEnd="@dimen/md_dialog_frame_margin"
|
||||||
|
android:paddingLeft="@dimen/md_dialog_frame_margin"
|
||||||
|
android:paddingRight="@dimen/md_dialog_frame_margin"
|
||||||
|
android:paddingStart="@dimen/md_dialog_frame_margin"
|
||||||
|
tools:gravity="start|center_vertical">
|
||||||
|
|
||||||
|
<com.kabouzeid.appthemehelper.common.views.ATECheckBox
|
||||||
|
android:id="@+id/checkbox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@null"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:gravity="center_vertical" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="@dimen/md_listitem_height"
|
||||||
|
android:paddingBottom="@dimen/md_listitem_vertical_margin_choice"
|
||||||
|
android:paddingLeft="@dimen/md_listitem_control_margin"
|
||||||
|
android:paddingStart="@dimen/md_listitem_control_margin"
|
||||||
|
android:paddingTop="@dimen/md_listitem_vertical_margin_choice"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textSize="@dimen/md_listitem_textsize"
|
||||||
|
tools:text="Item" />
|
||||||
|
|
||||||
|
<com.kabouzeid.gramophone.views.IconImageView
|
||||||
|
android:id="@+id/drag_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:minHeight="@dimen/md_listitem_height"
|
||||||
|
android:tint="?attr/iconColor"
|
||||||
|
android:tintMode="src_in"
|
||||||
|
app:srcCompat="@drawable/ic_drag_vertical_white_24dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -140,6 +140,7 @@
|
||||||
<string name="remove_action">Entfernen</string>
|
<string name="remove_action">Entfernen</string>
|
||||||
<string name="rename_action">Umbenennen</string>
|
<string name="rename_action">Umbenennen</string>
|
||||||
<string name="create_action">Erstellen</string>
|
<string name="create_action">Erstellen</string>
|
||||||
|
<string name="reset_action">Zurücksetzen</string>
|
||||||
<string name="x_selected">%1$d ausgewählt</string>
|
<string name="x_selected">%1$d ausgewählt</string>
|
||||||
<string name="primary_color">Hauptfarbe</string>
|
<string name="primary_color">Hauptfarbe</string>
|
||||||
<string name="accent_color">Akzentfarbe</string>
|
<string name="accent_color">Akzentfarbe</string>
|
||||||
|
|
@ -284,4 +285,8 @@
|
||||||
<string name="pref_summary_blacklist">Der Inhalt der Ordner auf der Blacklist wird in deiner Bibliothek verborgen.</string>
|
<string name="pref_summary_blacklist">Der Inhalt der Ordner auf der Blacklist wird in deiner Bibliothek verborgen.</string>
|
||||||
<string name="reset_artist_image">Künstler-Bild zurücksetzen</string>
|
<string name="reset_artist_image">Künstler-Bild zurücksetzen</string>
|
||||||
<string name="set_artist_image">Künstler-Bild festlegen</string>
|
<string name="set_artist_image">Künstler-Bild festlegen</string>
|
||||||
|
<string name="library_categories">Bibliothek</string>
|
||||||
|
<string name="pref_summary_library_categories">Anzeige und Anordnung der einzelnen Kategorien festlegen.</string>
|
||||||
|
<string name="edit_categories">Kategorien bearbeiten</string>
|
||||||
|
<string name="at_least_one_category_must_be_enabled">Zumindest eine Kategorie muss aktiv sein.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@
|
||||||
<string name="remove_action">Remove</string>
|
<string name="remove_action">Remove</string>
|
||||||
<string name="rename_action">Rename</string>
|
<string name="rename_action">Rename</string>
|
||||||
<string name="create_action">Create</string>
|
<string name="create_action">Create</string>
|
||||||
|
<string name="reset_action">Reset</string>
|
||||||
<string name="x_selected">%1$d selected</string>
|
<string name="x_selected">%1$d selected</string>
|
||||||
<string name="primary_color">Primary color</string>
|
<string name="primary_color">Primary color</string>
|
||||||
<string name="accent_color">Accent color</string>
|
<string name="accent_color">Accent color</string>
|
||||||
|
|
@ -294,4 +295,8 @@
|
||||||
<string name="pref_summary_blacklist">The content of blacklisted folders is hidden from your library.</string>
|
<string name="pref_summary_blacklist">The content of blacklisted folders is hidden from your library.</string>
|
||||||
<string name="reset_artist_image">Reset artist image</string>
|
<string name="reset_artist_image">Reset artist image</string>
|
||||||
<string name="set_artist_image">Set artist image</string>
|
<string name="set_artist_image">Set artist image</string>
|
||||||
|
<string name="library_categories">Library categories</string>
|
||||||
|
<string name="pref_summary_library_categories">Configure visibility and order of library categories.</string>
|
||||||
|
<string name="edit_categories">Edit categories</string>
|
||||||
|
<string name="at_least_one_category_must_be_enabled">At least one category must be enabled.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,11 @@
|
||||||
android:positiveButtonText="@null"
|
android:positiveButtonText="@null"
|
||||||
android:title="@string/pref_title_general_theme" />
|
android:title="@string/pref_title_general_theme" />
|
||||||
|
|
||||||
|
<com.kabouzeid.gramophone.preferences.LibraryPreference
|
||||||
|
android:key="library_categories"
|
||||||
|
android:summary="@string/pref_summary_library_categories"
|
||||||
|
android:title="@string/library_categories" />
|
||||||
|
|
||||||
</com.kabouzeid.appthemehelper.common.prefs.supportv7.ATEPreferenceCategory>
|
</com.kabouzeid.appthemehelper.common.prefs.supportv7.ATEPreferenceCategory>
|
||||||
|
|
||||||
</android.support.v7.preference.PreferenceScreen>
|
</android.support.v7.preference.PreferenceScreen>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue