• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.settings.widget;
17 
18 import android.content.res.TypedArray;
19 import android.os.Bundle;
20 import android.widget.ArrayAdapter;
21 
22 import androidx.annotation.VisibleForTesting;
23 import androidx.appcompat.app.AlertDialog.Builder;
24 import androidx.preference.ListPreference;
25 import androidx.preference.PreferenceDialogFragmentCompat;
26 
27 import com.android.settingslib.core.instrumentation.Instrumentable;
28 
29 import java.util.ArrayList;
30 
31 /**
32  * {@link PreferenceDialogFragmentCompat} that updates the available options
33  * when {@code onListPreferenceUpdated} is called."
34  */
35 public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragmentCompat implements
36         Instrumentable {
37 
38     private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
39     private static final String SAVE_STATE_ENTRIES =
40             "UpdatableListPreferenceDialogFragment.entries";
41     private static final String SAVE_STATE_ENTRY_VALUES =
42             "UpdatableListPreferenceDialogFragment.entryValues";
43     private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
44     private ArrayAdapter mAdapter;
45     private int mClickedDialogEntryIndex;
46     private ArrayList<CharSequence> mEntries;
47     private CharSequence[] mEntryValues;
48     private int mMetricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
49 
newInstance( String key, int metricsCategory)50     public static UpdatableListPreferenceDialogFragment newInstance(
51             String key, int metricsCategory) {
52         UpdatableListPreferenceDialogFragment fragment =
53                 new UpdatableListPreferenceDialogFragment();
54         Bundle args = new Bundle(1);
55         args.putString(ARG_KEY, key);
56         args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
57         fragment.setArguments(args);
58         return fragment;
59     }
60 
onCreate(Bundle savedInstanceState)61     public void onCreate(Bundle savedInstanceState) {
62         super.onCreate(savedInstanceState);
63         final Bundle bundle = getArguments();
64         mMetricsCategory =
65                 bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
66         if (savedInstanceState == null) {
67             mEntries = new ArrayList<>();
68             setPreferenceData(getListPreference());
69         } else {
70             mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
71             mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
72             mEntryValues =
73                     savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
74         }
75     }
76 
77     @Override
onSaveInstanceState(Bundle outState)78     public void onSaveInstanceState(Bundle outState) {
79         super.onSaveInstanceState(outState);
80         outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
81         outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
82         outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
83     }
84 
85     @Override
onDialogClosed(boolean positiveResult)86     public void onDialogClosed(boolean positiveResult) {
87         if (positiveResult && mClickedDialogEntryIndex >= 0) {
88             final ListPreference preference = getListPreference();
89             final String value = mEntryValues[mClickedDialogEntryIndex].toString();
90             if (preference.callChangeListener(value)) {
91                 preference.setValue(value);
92             }
93         }
94     }
95 
96     @VisibleForTesting
setAdapter(ArrayAdapter adapter)97     void setAdapter(ArrayAdapter adapter) {
98         mAdapter = adapter;
99     }
100 
101     @VisibleForTesting
setEntries(ArrayList<CharSequence> entries)102     void setEntries(ArrayList<CharSequence> entries) {
103         mEntries = entries;
104     }
105 
106     @VisibleForTesting
getAdapter()107     ArrayAdapter getAdapter() {
108         return mAdapter;
109     }
110 
111     @VisibleForTesting
setMetricsCategory(Bundle bundle)112     void setMetricsCategory(Bundle bundle) {
113         mMetricsCategory =
114                 bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
115     }
116 
117     @Override
onPrepareDialogBuilder(Builder builder)118     protected void onPrepareDialogBuilder(Builder builder) {
119         super.onPrepareDialogBuilder(builder);
120         final TypedArray a = getContext().obtainStyledAttributes(
121                 null,
122                 com.android.internal.R.styleable.AlertDialog,
123                 com.android.internal.R.attr.alertDialogStyle, 0);
124 
125         mAdapter = new ArrayAdapter<>(
126                 getContext(),
127                 a.getResourceId(
128                         com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
129                         com.android.internal.R.layout.select_dialog_singlechoice),
130                 mEntries);
131 
132         builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
133                 (dialog, which) -> {
134                     mClickedDialogEntryIndex = which;
135                     onClick(dialog, -1);
136                     dialog.dismiss();
137                 });
138         builder.setPositiveButton(null, null);
139         a.recycle();
140     }
141 
142     @Override
getMetricsCategory()143     public int getMetricsCategory() {
144         return mMetricsCategory;
145     }
146 
147     @VisibleForTesting
getListPreference()148     ListPreference getListPreference() {
149         return (ListPreference) getPreference();
150     }
151 
setPreferenceData(ListPreference preference)152     private void setPreferenceData(ListPreference preference) {
153         mEntries.clear();
154         mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
155         for (CharSequence entry : preference.getEntries()) {
156             mEntries.add(entry);
157         }
158         mEntryValues = preference.getEntryValues();
159     }
160 
onListPreferenceUpdated(ListPreference preference)161     public void onListPreferenceUpdated(ListPreference preference) {
162         if (mAdapter != null) {
163             setPreferenceData(preference);
164             mAdapter.notifyDataSetChanged();
165         }
166     }
167 }
168