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