diff --git a/app/build.gradle b/app/build.gradle index 9205138b..a37e4894 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -125,6 +125,7 @@ dependencies { implementation('com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.11.0@aar') { 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:answers:1.3.13@aar') { transitive = true diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/CategoryInfoAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/CategoryInfoAdapter.java new file mode 100644 index 00000000..7f412e71 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/CategoryInfoAdapter.java @@ -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 implements SwipeAndDragHelper.ActionCompletionContract { + private ArrayList categoryInfos; + private ItemTouchHelper touchHelper; + + public CategoryInfoAdapter(ArrayList 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 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 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); + } + } +} + 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..9929a0c6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/MusicLibraryPagerAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/MusicLibraryPagerAdapter.java @@ -9,15 +9,17 @@ import android.support.v4.app.FragmentPagerAdapter; import android.util.SparseArray; 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.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 +32,28 @@ 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); - } + setCategoryInfos(PreferenceUtil.getInstance(context).getLibraryCategoryInfos()); } - @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 setCategoryInfos(@NonNull ArrayList categoryInfos) { + mHolderList.clear(); - final int mPosition = mHolderList.size(); - mHolderList.add(mPosition, mHolder); + for (CategoryInfo categoryInfo : categoryInfos) { + 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(); } @@ -68,6 +65,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,16 +118,40 @@ 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), + SONGS(SongsFragment.class), + ALBUMS(AlbumsFragment.class), + ARTISTS(ArtistsFragment.class), GENRES(GenresFragment.class), - PLAYLIST(PlaylistsFragment.class); + PLAYLISTS(PlaylistsFragment.class); private final Class mFragmentClass; @@ -124,10 +162,25 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter { public Class getFragmentClass() { 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 { String mClassName; Bundle mParams; + String title; } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/model/CategoryInfo.java b/app/src/main/java/com/kabouzeid/gramophone/model/CategoryInfo.java new file mode 100644 index 00000000..109f4352 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/model/CategoryInfo.java @@ -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; + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/preferences/LibraryPreference.java b/app/src/main/java/com/kabouzeid/gramophone/preferences/LibraryPreference.java new file mode 100644 index 00000000..7993d30d --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/preferences/LibraryPreference.java @@ -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); + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/preferences/LibraryPreferenceDialog.java b/app/src/main/java/com/kabouzeid/gramophone/preferences/LibraryPreferenceDialog.java new file mode 100644 index 00000000..23191dd3 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/preferences/LibraryPreferenceDialog.java @@ -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 categories) { + if (getSelected(categories) == 0) return; + + PreferenceUtil.getInstance(getContext()).setLibraryCategoryInfos(categories); + } + + private int getSelected(ArrayList categories) { + int selected = 0; + for (CategoryInfo categoryInfo : categories) { + if (categoryInfo.visible) + selected++; + } + return selected; + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java index f593c912..8e2d9e6e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java @@ -31,6 +31,8 @@ import com.kabouzeid.gramophone.appshortcuts.DynamicShortcutManager; import com.kabouzeid.gramophone.misc.NonProAllowedColors; import com.kabouzeid.gramophone.preferences.BlacklistPreference; 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.NowPlayingScreenPreferenceDialog; import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity; @@ -167,6 +169,8 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia return NowPlayingScreenPreferenceDialog.newInstance(); } else if (preference instanceof BlacklistPreference) { return BlacklistPreferenceDialog.newInstance(); + } else if (preference instanceof LibraryPreference) { + return LibraryPreferenceDialog.newInstance(); } return super.onCreatePreferenceDialog(preference); } 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..5dbdbd7e 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.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() { 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..73b5c25a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java @@ -7,12 +7,18 @@ import android.preference.PreferenceManager; import android.support.annotation.NonNull; 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.helper.SortOrder; +import com.kabouzeid.gramophone.model.CategoryInfo; import com.kabouzeid.gramophone.ui.fragments.mainactivity.folders.FoldersFragment; import com.kabouzeid.gramophone.ui.fragments.player.NowPlayingScreen; import java.io.File; +import java.lang.reflect.Type; +import java.util.ArrayList; public final class PreferenceUtil { 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 LIBRARY_CATEGORIES = "library_categories"; + private static PreferenceUtil sInstance; private final SharedPreferences mPreferences; @@ -426,4 +434,41 @@ public final class PreferenceUtil { public final boolean initializedBlacklist() { return mPreferences.getBoolean(INITIALIZED_BLACKLIST, false); } + + public void setLibraryCategoryInfos(ArrayList categories) { + Gson gson = new Gson(); + Type collectionType = new TypeToken>() { + }.getType(); + + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putString(LIBRARY_CATEGORIES, gson.toJson(categories, collectionType)); + editor.apply(); + } + + public ArrayList getLibraryCategoryInfos() { + String data = mPreferences.getString(LIBRARY_CATEGORIES, null); + if (data != null) { + Gson gson = new Gson(); + Type collectionType = new TypeToken>() { + }.getType(); + + try { + return gson.fromJson(data, collectionType); + } catch (JsonSyntaxException e) { + e.printStackTrace(); + } + } + + return getDefaultLibraryCategoryInfos(); + } + + public ArrayList getDefaultLibraryCategoryInfos() { + ArrayList 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; + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/SwipeAndDragHelper.java b/app/src/main/java/com/kabouzeid/gramophone/util/SwipeAndDragHelper.java new file mode 100644 index 00000000..3e28263d --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/util/SwipeAndDragHelper.java @@ -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); + } + +} + diff --git a/app/src/main/res/layout/preference_dialog_library_categories.xml b/app/src/main/res/layout/preference_dialog_library_categories.xml new file mode 100644 index 00000000..4782ec71 --- /dev/null +++ b/app/src/main/res/layout/preference_dialog_library_categories.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/layout/preference_dialog_library_categories_listitem.xml b/app/src/main/res/layout/preference_dialog_library_categories_listitem.xml new file mode 100644 index 00000000..d76d4deb --- /dev/null +++ b/app/src/main/res/layout/preference_dialog_library_categories_listitem.xml @@ -0,0 +1,56 @@ + + + + + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 1befbdde..0c8fbb68 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -140,6 +140,7 @@ Entfernen Umbenennen Erstellen + Zurücksetzen %1$d ausgewählt Hauptfarbe Akzentfarbe @@ -284,4 +285,8 @@ Der Inhalt der Ordner auf der Blacklist wird in deiner Bibliothek verborgen. Künstler-Bild zurücksetzen Künstler-Bild festlegen + Bibliothek + Anzeige und Anordnung der einzelnen Kategorien festlegen. + Kategorien bearbeiten + Zumindest eine Kategorie muss aktiv sein. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0a05e391..0fd77e6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -141,6 +141,7 @@ Remove Rename Create + Reset %1$d selected Primary color Accent color @@ -294,4 +295,8 @@ The content of blacklisted folders is hidden from your library. Reset artist image Set artist image + Library categories + Configure visibility and order of library categories. + Edit categories + At least one category must be enabled. diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index ed43ede6..56816287 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -20,6 +20,11 @@ android:positiveButtonText="@null" android:title="@string/pref_title_general_theme" /> + +