Merge branch 'library-categories' of https://github.com/doompadee/Phonograph into doompadee-library-categories

This commit is contained in:
Karim Abou Zeid 2017-12-25 23:42:32 +01:00
commit ffa33fced7
14 changed files with 567 additions and 29 deletions

View file

@ -0,0 +1,95 @@
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.Category;
import com.kabouzeid.gramophone.util.SwipeAndDragHelper;
import java.util.ArrayList;
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> implements SwipeAndDragHelper.ActionCompletionContract {
private ArrayList<Category> categories;
private ItemTouchHelper touchHelper;
public CategoryAdapter(ArrayList<Category> categories) {
this.categories = categories;
}
@Override
public CategoryAdapter.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(CategoryAdapter.ViewHolder holder, int position) {
Category category = categories.get(position);
holder.checkBox.setChecked(category.visible);
holder.title.setText(holder.title.getResources().getString(category.id.key));
holder.itemView.setOnClickListener(v -> {
category.visible = !category.visible;
holder.checkBox.setChecked(category.visible);
});
holder.dragView.setOnTouchListener((view, event) -> {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
touchHelper.startDrag(holder);
}
return false;
}
);
}
@Override
public int getItemCount() {
return categories.size();
}
public void setCategories(ArrayList<Category> categories) {
this.categories = categories;
notifyDataSetChanged();
}
@Override
public void onViewMoved(int oldPosition, int newPosition) {
Category category = categories.get(oldPosition);
categories.remove(oldPosition);
categories.add(newPosition, category);
notifyItemMoved(oldPosition, newPosition);
}
public void setTouchHelper(ItemTouchHelper touchHelper) {
this.touchHelper = touchHelper;
}
public ArrayList<Category> getCategories() {
return categories;
}
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);
}
}
}

View file

@ -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<? extends Fragment> className, final Bundle params) {
final Holder mHolder = new Holder();
mHolder.mClassName = className.getName();
mHolder.mParams = params;
public void setCategories(@NonNull ArrayList<Category> 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(category.id.key)
.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,16 +120,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<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 {
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<? extends Fragment> mFragmentClass;
@ -124,10 +164,25 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
public Class<? extends Fragment> 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;
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,87 @@
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.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.CategoryAdapter;
import com.kabouzeid.gramophone.model.Category;
import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.kabouzeid.gramophone.util.SwipeAndDragHelper;
import java.util.ArrayList;
public class LibraryPreferenceDialog extends DialogFragment {
public static LibraryPreferenceDialog newInstance() {
return new LibraryPreferenceDialog();
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.preference_dialog_library_categories, null);
ArrayList<Category> categories = PreferenceUtil.getInstance(getContext()).getLibraryCategories();
RecyclerView categoriesView = view.findViewById(R.id.recycler_view);
categoriesView.setLayoutManager(new LinearLayoutManager(getActivity()));
CategoryAdapter adapter = new CategoryAdapter(categories);
SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(adapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(swipeAndDragHelper);
adapter.setTouchHelper(touchHelper);
categoriesView.setAdapter(adapter);
touchHelper.attachToRecyclerView(categoriesView);
MaterialDialog dialog = 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((dialog1, action) -> {
adapter.setCategories(PreferenceUtil.getInstance(getContext()).getDefaultLibraryCategories());
})
.onNegative((dialog12, action) -> dismiss())
.onPositive((dialog13, action) -> {
if (!updateCategories(adapter.getCategories())) {
new MaterialDialog.Builder(getContext())
.title(R.string.edit_categories)
.content(R.string.at_least_one_category_must_be_enabled)
.positiveText(android.R.string.ok)
.show();
} else {
dismiss();
}
})
.build();
return dialog;
}
private boolean updateCategories(ArrayList<Category> categories) {
if (getSelected(categories) == 0) return false;
PreferenceUtil.getInstance(getContext()).setLibraryCategories(categories);
return true;
}
private int getSelected(ArrayList<Category> categories) {
int selected = 0;
for (Category category : categories) {
if (category.visible)
selected++;
}
return selected;
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -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,47 @@ public final class PreferenceUtil {
public final boolean initializedBlacklist() {
return mPreferences.getBoolean(INITIALIZED_BLACKLIST, false);
}
public void setLibraryCategories(ArrayList<Category> categories) {
Gson gson = new Gson();
Set<String> 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<Category> getLibraryCategories() {
Set<String> data = mPreferences.getStringSet(LIBRARY_CATEGORIES, null);
if (data != null) {
Gson gson = new Gson();
ArrayList<Category> 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 getDefaultLibraryCategories();
}
public ArrayList<Category> getDefaultLibraryCategories() {
ArrayList<Category> 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;
}
}

View file

@ -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);
}
}

View file

@ -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>

View file

@ -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>

View file

@ -140,6 +140,7 @@
<string name="remove_action">Entfernen</string>
<string name="rename_action">Umbenennen</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="primary_color">Hauptfarbe</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="reset_artist_image">Künstler-Bild zurücksetzen</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>

View file

@ -141,6 +141,7 @@
<string name="remove_action">Remove</string>
<string name="rename_action">Rename</string>
<string name="create_action">Create</string>
<string name="reset_action">Reset</string>
<string name="x_selected">%1$d selected</string>
<string name="primary_color">Primary 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="reset_artist_image">Reset 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>

View file

@ -20,6 +20,11 @@
android:positiveButtonText="@null"
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>
</android.support.v7.preference.PreferenceScreen>