package com.thomasdh.roosterpgplus.CustomUI; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.content.res.TypedArray; import android.preference.ListPreference; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.widget.ListView; import com.thomasdh.roosterpgplus.R; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class ListPreferenceMultiSelect extends ListPreference { private static final String DEFAULT_SEPARATOR = "OV=I=XseparatorX=I=VO"; private final String separator; private String checkAllKey = null; private boolean[] mClickedDialogEntryIndices; // Constructor public ListPreferenceMultiSelect(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPreferenceMultiSelect); if (a != null) { checkAllKey = a.getString(R.styleable.ListPreferenceMultiSelect_checkAll); } String s = a != null ? a.getString(R.styleable.ListPreferenceMultiSelect_separator) : null; if (s != null) { separator = s; } else { separator = DEFAULT_SEPARATOR; } // Initialize the array of boolean to the same size as number of entries CharSequence[] entries = getEntries(); mClickedDialogEntryIndices = new boolean[entries != null ? entries.length : 0]; } // Credits to kurellajunior on this post http://snippets.dzone.com/posts/show/91 protected static String join(Iterable<?> pColl, String separator) { Iterator<?> oIter; if (pColl == null || !(oIter = pColl.iterator()).hasNext()) return ""; StringBuilder oBuilder = new StringBuilder(String.valueOf(oIter.next())); while (oIter.hasNext()) oBuilder.append(separator).append(oIter.next()); return oBuilder.toString(); } public void setEntries(CharSequence[] entries, boolean[] enabled) { setEntries(entries); mClickedDialogEntryIndices = enabled; } @Override public void setEntries(CharSequence[] entries) { super.setEntries(entries); // Initialize the array of boolean to the same size as number of entries mClickedDialogEntryIndices = new boolean[entries.length]; } @Override protected void onPrepareDialogBuilder(@NonNull Builder builder) { CharSequence[] entries = getEntries(); CharSequence[] entryValues = getEntryValues(); if (entries == null || entryValues == null || entries.length != entryValues.length) { throw new IllegalStateException( "ListPreference requires an entries array and an entryValues array which are both the same length"); } restoreCheckedEntries(); builder.setMultiChoiceItems(entries, mClickedDialogEntryIndices, (dialog, which, val) -> { if (isCheckAllValue(which)) { checkAll(dialog, val); } mClickedDialogEntryIndices[which] = val; } ); } private boolean isCheckAllValue(int which) { CharSequence[] entryValues = getEntryValues(); return checkAllKey != null && entryValues[which].equals(checkAllKey); } private void checkAll(DialogInterface dialog, boolean val) { ListView lv = ((AlertDialog) dialog).getListView(); int size = lv.getCount(); for (int i = 0; i < size; i++) { lv.setItemChecked(i, val); mClickedDialogEntryIndices[i] = val; } } public String[] parseStoredValue(CharSequence val) { if ("".equals(val)) { return null; } else { return ((String) val).split(separator); } } private void restoreCheckedEntries() { CharSequence[] entryValues = getEntryValues(); // Explode the string read in sharedpreferences String[] vals = parseStoredValue(getValue()); if (vals != null) { List<String> valuesList = Arrays.asList(vals); // for ( int j=0; j<vals.length; j++ ) { // // String val = vals[j].trim(); for (int i = 0; i < entryValues.length; i++) { CharSequence entry = entryValues[i]; if (valuesList.contains(entry)) { mClickedDialogEntryIndices[i] = true; } } // } } } @Override protected void onDialogClosed(boolean positiveResult) { // super.onDialogClosed(positiveResult); ArrayList<String> values = new ArrayList<>(); CharSequence[] entryValues = getEntryValues(); if (positiveResult && entryValues != null) { for (int i = 0; i < entryValues.length; i++) { if (mClickedDialogEntryIndices[i]) { // Don't save the state of check all option - if any String val = (String) entryValues[i]; if (checkAllKey == null || !val.equals(checkAllKey)) { values.add(val); } } } if (callChangeListener(values)) { setValue(join(values, separator)); } } } }