• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 com.android.settings;
18 
19 import android.app.Dialog;
20 import android.app.settings.SettingsEnums;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.DialogInterface.OnClickListener;
24 import android.content.Intent;
25 import android.os.Bundle;
26 import android.util.AttributeSet;
27 
28 import androidx.appcompat.app.AlertDialog.Builder;
29 import androidx.fragment.app.Fragment;
30 import androidx.fragment.app.FragmentTransaction;
31 import androidx.preference.ListPreference;
32 import androidx.preference.ListPreferenceDialogFragmentCompat;
33 
34 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
35 
36 public class CustomListPreference extends ListPreference {
37 
CustomListPreference(Context context, AttributeSet attrs)38     public CustomListPreference(Context context, AttributeSet attrs) {
39         super(context, attrs);
40         setSingleLineTitle(true);
41     }
42 
CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)43     public CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr,
44             int defStyleRes) {
45         super(context, attrs, defStyleAttr, defStyleRes);
46     }
47 
onPrepareDialogBuilder(Builder builder, DialogInterface.OnClickListener listener)48     protected void onPrepareDialogBuilder(Builder builder,
49             DialogInterface.OnClickListener listener) {
50     }
51 
onDialogClosed(boolean positiveResult)52     protected void onDialogClosed(boolean positiveResult) {
53     }
54 
onDialogCreated(Dialog dialog)55     protected void onDialogCreated(Dialog dialog) {
56     }
57 
isAutoClosePreference()58     protected boolean isAutoClosePreference() {
59         return true;
60     }
61 
62     /**
63      * Called when a user is about to choose the given value, to determine if we
64      * should show a confirmation dialog.
65      *
66      * @param value the value the user is about to choose
67      * @return the message to show in a confirmation dialog, or {@code null} to
68      * not request confirmation
69      */
getConfirmationMessage(String value)70     protected CharSequence getConfirmationMessage(String value) {
71         return null;
72     }
73 
onDialogStateRestored(Dialog dialog, Bundle savedInstanceState)74     protected void onDialogStateRestored(Dialog dialog, Bundle savedInstanceState) {
75     }
76 
77     public static class CustomListPreferenceDialogFragment extends
78             ListPreferenceDialogFragmentCompat {
79 
80         private static final java.lang.String KEY_CLICKED_ENTRY_INDEX
81                 = "settings.CustomListPrefDialog.KEY_CLICKED_ENTRY_INDEX";
82 
83         private int mClickedDialogEntryIndex;
84 
newInstance(String key)85         public static ListPreferenceDialogFragmentCompat newInstance(String key) {
86             final ListPreferenceDialogFragmentCompat fragment =
87                     new CustomListPreferenceDialogFragment();
88             final Bundle b = new Bundle(1);
89             b.putString(ARG_KEY, key);
90             fragment.setArguments(b);
91             return fragment;
92         }
93 
getCustomizablePreference()94         private CustomListPreference getCustomizablePreference() {
95             return (CustomListPreference) getPreference();
96         }
97 
98         @Override
onPrepareDialogBuilder(Builder builder)99         protected void onPrepareDialogBuilder(Builder builder) {
100             super.onPrepareDialogBuilder(builder);
101             mClickedDialogEntryIndex = getCustomizablePreference()
102                     .findIndexOfValue(getCustomizablePreference().getValue());
103             getCustomizablePreference().onPrepareDialogBuilder(builder, getOnItemClickListener());
104             if (!getCustomizablePreference().isAutoClosePreference()) {
105                 builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
106                     @Override
107                     public void onClick(DialogInterface dialog, int which) {
108                         onItemChosen();
109                     }
110                 });
111             }
112         }
113 
114         @Override
onCreateDialog(Bundle savedInstanceState)115         public Dialog onCreateDialog(Bundle savedInstanceState) {
116             Dialog dialog = super.onCreateDialog(savedInstanceState);
117             if (savedInstanceState != null) {
118                 mClickedDialogEntryIndex = savedInstanceState.getInt(KEY_CLICKED_ENTRY_INDEX,
119                         mClickedDialogEntryIndex);
120             }
121             getCustomizablePreference().onDialogCreated(dialog);
122             return dialog;
123         }
124 
125         @Override
onSaveInstanceState(Bundle outState)126         public void onSaveInstanceState(Bundle outState) {
127             super.onSaveInstanceState(outState);
128             outState.putInt(KEY_CLICKED_ENTRY_INDEX, mClickedDialogEntryIndex);
129         }
130 
131         @Override
onActivityCreated(Bundle savedInstanceState)132         public void onActivityCreated(Bundle savedInstanceState) {
133             super.onActivityCreated(savedInstanceState);
134             getCustomizablePreference().onDialogStateRestored(getDialog(), savedInstanceState);
135         }
136 
getOnItemClickListener()137         protected DialogInterface.OnClickListener getOnItemClickListener() {
138             return new DialogInterface.OnClickListener() {
139                 @Override
140                 public void onClick(DialogInterface dialog, int which) {
141                     setClickedDialogEntryIndex(which);
142                     if (getCustomizablePreference().isAutoClosePreference()) {
143                         onItemChosen();
144                     }
145                 }
146             };
147         }
148 
setClickedDialogEntryIndex(int which)149         protected void setClickedDialogEntryIndex(int which) {
150             mClickedDialogEntryIndex = which;
151         }
152 
getValue()153         private String getValue() {
154             final ListPreference preference = getCustomizablePreference();
155             if (mClickedDialogEntryIndex >= 0 && preference.getEntryValues() != null) {
156                 return preference.getEntryValues()[mClickedDialogEntryIndex].toString();
157             } else {
158                 return null;
159             }
160         }
161 
162         /**
163          * Called when user has made a concrete item choice, but we might need
164          * to make a quick detour to confirm that choice with a second dialog.
165          */
onItemChosen()166         protected void onItemChosen() {
167             final CharSequence message = getCustomizablePreference()
168                     .getConfirmationMessage(getValue());
169             if (message != null) {
170                 final Fragment f = new ConfirmDialogFragment();
171                 final Bundle args = new Bundle();
172                 args.putCharSequence(Intent.EXTRA_TEXT, message);
173                 f.setArguments(args);
174                 f.setTargetFragment(CustomListPreferenceDialogFragment.this, 0);
175                 final FragmentTransaction ft = getFragmentManager().beginTransaction();
176                 ft.add(f, getTag() + "-Confirm");
177                 ft.commitAllowingStateLoss();
178             } else {
179                 onItemConfirmed();
180             }
181         }
182 
183         /**
184          * Called when user has made a concrete item choice and we've fully
185          * confirmed they want to move forward (if we took a detour above).
186          */
onItemConfirmed()187         protected void onItemConfirmed() {
188             onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
189             getDialog().dismiss();
190         }
191 
192         @Override
onDialogClosed(boolean positiveResult)193         public void onDialogClosed(boolean positiveResult) {
194             getCustomizablePreference().onDialogClosed(positiveResult);
195             final ListPreference preference = getCustomizablePreference();
196             final String value = getValue();
197             if (positiveResult && value != null) {
198                 if (preference.callChangeListener(value)) {
199                     preference.setValue(value);
200                 }
201             }
202         }
203     }
204 
205     public static class ConfirmDialogFragment extends InstrumentedDialogFragment {
206         @Override
207         public Dialog onCreateDialog(Bundle savedInstanceState) {
208             return new Builder(getActivity())
209                     .setMessage(getArguments().getCharSequence(Intent.EXTRA_TEXT))
210                     .setPositiveButton(android.R.string.ok, new OnClickListener() {
211                         @Override
212                         public void onClick(DialogInterface dialog, int which) {
213                             final Fragment f = getTargetFragment();
214                             if (f != null) {
215                                 ((CustomListPreferenceDialogFragment) f).onItemConfirmed();
216                             }
217                         }
218                     })
219                     .setNegativeButton(android.R.string.cancel, null)
220                     .create();
221         }
222 
223         @Override
224         public int getMetricsCategory() {
225             return SettingsEnums.DIALOG_CUSTOM_LIST_CONFIRMATION;
226         }
227     }
228 }
229