1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.preference; 18 19 import android.content.DialogInterface; 20 import android.os.Bundle; 21 22 import androidx.annotation.NonNull; 23 import androidx.appcompat.app.AlertDialog; 24 import androidx.preference.internal.AbstractMultiSelectListPreference; 25 26 import java.util.ArrayList; 27 import java.util.HashSet; 28 import java.util.Set; 29 30 public class MultiSelectListPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat { 31 32 private static final String SAVE_STATE_VALUES = 33 "MultiSelectListPreferenceDialogFragmentCompat.values"; 34 private static final String SAVE_STATE_CHANGED = 35 "MultiSelectListPreferenceDialogFragmentCompat.changed"; 36 private static final String SAVE_STATE_ENTRIES = 37 "MultiSelectListPreferenceDialogFragmentCompat.entries"; 38 private static final String SAVE_STATE_ENTRY_VALUES = 39 "MultiSelectListPreferenceDialogFragmentCompat.entryValues"; 40 41 private Set<String> mNewValues = new HashSet<>(); 42 private boolean mPreferenceChanged; 43 private CharSequence[] mEntries; 44 private CharSequence[] mEntryValues; 45 46 public static MultiSelectListPreferenceDialogFragmentCompat newInstance(String key) { 47 final MultiSelectListPreferenceDialogFragmentCompat fragment = 48 new MultiSelectListPreferenceDialogFragmentCompat(); 49 final Bundle b = new Bundle(1); 50 b.putString(ARG_KEY, key); 51 fragment.setArguments(b); 52 return fragment; 53 } 54 55 @Override 56 public void onCreate(Bundle savedInstanceState) { 57 super.onCreate(savedInstanceState); 58 59 if (savedInstanceState == null) { 60 final AbstractMultiSelectListPreference preference = getListPreference(); 61 62 if (preference.getEntries() == null || preference.getEntryValues() == null) { 63 throw new IllegalStateException( 64 "MultiSelectListPreference requires an entries array and " + 65 "an entryValues array."); 66 } 67 68 mNewValues.clear(); 69 mNewValues.addAll(preference.getValues()); 70 mPreferenceChanged = false; 71 mEntries = preference.getEntries(); 72 mEntryValues = preference.getEntryValues(); 73 } else { 74 mNewValues.clear(); 75 mNewValues.addAll(savedInstanceState.getStringArrayList(SAVE_STATE_VALUES)); 76 mPreferenceChanged = savedInstanceState.getBoolean(SAVE_STATE_CHANGED, false); 77 mEntries = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRIES); 78 mEntryValues = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES); 79 } 80 } 81 82 @Override 83 public void onSaveInstanceState(@NonNull Bundle outState) { 84 super.onSaveInstanceState(outState); 85 outState.putStringArrayList(SAVE_STATE_VALUES, new ArrayList<>(mNewValues)); 86 outState.putBoolean(SAVE_STATE_CHANGED, mPreferenceChanged); 87 outState.putCharSequenceArray(SAVE_STATE_ENTRIES, mEntries); 88 outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues); 89 } 90 91 private AbstractMultiSelectListPreference getListPreference() { 92 return (AbstractMultiSelectListPreference) getPreference(); 93 } 94 95 @Override 96 protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 97 super.onPrepareDialogBuilder(builder); 98 99 final int entryCount = mEntryValues.length; 100 final boolean[] checkedItems = new boolean[entryCount]; 101 for (int i = 0; i < entryCount; i++) { 102 checkedItems[i] = mNewValues.contains(mEntryValues[i].toString()); 103 } 104 builder.setMultiChoiceItems(mEntries, checkedItems, 105 new DialogInterface.OnMultiChoiceClickListener() { 106 @Override 107 public void onClick(DialogInterface dialog, int which, boolean isChecked) { 108 if (isChecked) { 109 mPreferenceChanged |= mNewValues.add( 110 mEntryValues[which].toString()); 111 } else { 112 mPreferenceChanged |= mNewValues.remove( 113 mEntryValues[which].toString()); 114 } 115 } 116 }); 117 } 118 119 @Override 120 public void onDialogClosed(boolean positiveResult) { 121 final AbstractMultiSelectListPreference preference = getListPreference(); 122 if (positiveResult && mPreferenceChanged) { 123 final Set<String> values = mNewValues; 124 if (preference.callChangeListener(values)) { 125 preference.setValues(values); 126 } 127 } 128 mPreferenceChanged = false; 129 } 130 } 131