1 /* 2 * Copyright (C) 2007 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 android.preference; 18 19 20 import android.content.Context; 21 import android.content.SharedPreferences; 22 import android.content.res.TypedArray; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.text.TextUtils; 26 import android.util.AttributeSet; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.view.ViewParent; 30 import android.widget.EditText; 31 32 /** 33 * A {@link Preference} that allows for string 34 * input. 35 * <p> 36 * It is a subclass of {@link DialogPreference} and shows the {@link EditText} 37 * in a dialog. This {@link EditText} can be modified either programmatically 38 * via {@link #getEditText()}, or through XML by setting any EditText 39 * attributes on the EditTextPreference. 40 * <p> 41 * This preference will store a string into the SharedPreferences. 42 * <p> 43 * See {@link android.R.styleable#EditText EditText Attributes}. 44 */ 45 public class EditTextPreference extends DialogPreference { 46 /** 47 * The edit text shown in the dialog. 48 */ 49 private EditText mEditText; 50 51 private String mText; 52 private boolean mTextSet; 53 54 public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 55 super(context, attrs, defStyleAttr, defStyleRes); 56 57 mEditText = new EditText(context, attrs); 58 59 // Give it an ID so it can be saved/restored 60 mEditText.setId(com.android.internal.R.id.edit); 61 62 /* 63 * The preference framework and view framework both have an 'enabled' 64 * attribute. Most likely, the 'enabled' specified in this XML is for 65 * the preference framework, but it was also given to the view framework. 66 * We reset the enabled state. 67 */ 68 mEditText.setEnabled(true); 69 } 70 71 public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) { 72 this(context, attrs, defStyleAttr, 0); 73 } 74 75 public EditTextPreference(Context context, AttributeSet attrs) { 76 this(context, attrs, com.android.internal.R.attr.editTextPreferenceStyle); 77 } 78 79 public EditTextPreference(Context context) { 80 this(context, null); 81 } 82 83 /** 84 * Saves the text to the {@link SharedPreferences}. 85 * 86 * @param text The text to save 87 */ 88 public void setText(String text) { 89 // Always persist/notify the first time. 90 final boolean changed = !TextUtils.equals(mText, text); 91 if (changed || !mTextSet) { 92 mText = text; 93 mTextSet = true; 94 persistString(text); 95 if(changed) { 96 notifyDependencyChange(shouldDisableDependents()); 97 notifyChanged(); 98 } 99 } 100 } 101 102 /** 103 * Gets the text from the {@link SharedPreferences}. 104 * 105 * @return The current preference value. 106 */ 107 public String getText() { 108 return mText; 109 } 110 111 @Override 112 protected void onBindDialogView(View view) { 113 super.onBindDialogView(view); 114 115 EditText editText = mEditText; 116 editText.setText(getText()); 117 118 ViewParent oldParent = editText.getParent(); 119 if (oldParent != view) { 120 if (oldParent != null) { 121 ((ViewGroup) oldParent).removeView(editText); 122 } 123 onAddEditTextToDialogView(view, editText); 124 } 125 } 126 127 /** 128 * Adds the EditText widget of this preference to the dialog's view. 129 * 130 * @param dialogView The dialog view. 131 */ 132 protected void onAddEditTextToDialogView(View dialogView, EditText editText) { 133 ViewGroup container = (ViewGroup) dialogView 134 .findViewById(com.android.internal.R.id.edittext_container); 135 if (container != null) { 136 container.addView(editText, ViewGroup.LayoutParams.MATCH_PARENT, 137 ViewGroup.LayoutParams.WRAP_CONTENT); 138 } 139 } 140 141 @Override 142 protected void onDialogClosed(boolean positiveResult) { 143 super.onDialogClosed(positiveResult); 144 145 if (positiveResult) { 146 String value = mEditText.getText().toString(); 147 if (callChangeListener(value)) { 148 setText(value); 149 } 150 } 151 } 152 153 @Override 154 protected Object onGetDefaultValue(TypedArray a, int index) { 155 return a.getString(index); 156 } 157 158 @Override 159 protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { 160 setText(restoreValue ? getPersistedString(mText) : (String) defaultValue); 161 } 162 163 @Override 164 public boolean shouldDisableDependents() { 165 return TextUtils.isEmpty(mText) || super.shouldDisableDependents(); 166 } 167 168 /** 169 * Returns the {@link EditText} widget that will be shown in the dialog. 170 * 171 * @return The {@link EditText} widget that will be shown in the dialog. 172 */ 173 public EditText getEditText() { 174 return mEditText; 175 } 176 177 /** @hide */ 178 @Override 179 protected boolean needInputMethod() { 180 // We want the input method to show, if possible, when dialog is displayed 181 return true; 182 } 183 184 @Override 185 protected Parcelable onSaveInstanceState() { 186 final Parcelable superState = super.onSaveInstanceState(); 187 if (isPersistent()) { 188 // No need to save instance state since it's persistent 189 return superState; 190 } 191 192 final SavedState myState = new SavedState(superState); 193 myState.text = getText(); 194 return myState; 195 } 196 197 @Override 198 protected void onRestoreInstanceState(Parcelable state) { 199 if (state == null || !state.getClass().equals(SavedState.class)) { 200 // Didn't save state for us in onSaveInstanceState 201 super.onRestoreInstanceState(state); 202 return; 203 } 204 205 SavedState myState = (SavedState) state; 206 super.onRestoreInstanceState(myState.getSuperState()); 207 setText(myState.text); 208 } 209 210 private static class SavedState extends BaseSavedState { 211 String text; 212 213 public SavedState(Parcel source) { 214 super(source); 215 text = source.readString(); 216 } 217 218 @Override 219 public void writeToParcel(Parcel dest, int flags) { 220 super.writeToParcel(dest, flags); 221 dest.writeString(text); 222 } 223 224 public SavedState(Parcelable superState) { 225 super(superState); 226 } 227 228 public static final Parcelable.Creator<SavedState> CREATOR = 229 new Parcelable.Creator<SavedState>() { 230 public SavedState createFromParcel(Parcel in) { 231 return new SavedState(in); 232 } 233 234 public SavedState[] newArray(int size) { 235 return new SavedState[size]; 236 } 237 }; 238 } 239 240 } 241