blob: ab3c6b418561e8e3dec1f171275d233edb2c14f4 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.emergency.preferences;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v14.preference.PreferenceDialogFragment;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;
import com.android.emergency.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.CustomDialogPreference;
/**
* Almost a copy of EditTextPreference that shows a {@link AutoCompleteTextView} instead of the
* basic EditText. It always show the suggested options.
* TODO: an EditTextPreference always shows the soft input keyboard, whereas this class does not,
* and it should, to mimic EditTextPreference better.
*/
public class AutoCompleteEditTextPreference extends CustomDialogPreference {
/**
* The edit text shown in the dialog.
*/
private AutoCompleteTextView mAutoCompleteTextView;
private String mText;
private boolean mTextSet;
public AutoCompleteEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mAutoCompleteTextView = new InstantAutoCompleteTextView(context, attrs);
// Give it an ID so it can be saved/restored
mAutoCompleteTextView.setId(R.id.edit);
/*
* The preference framework and view framework both have an 'enabled'
* attribute. Most likely, the 'enabled' specified in this XML is for
* the preference framework, but it was also given to the view framework.
* We reset the enabled state.
*/
mAutoCompleteTextView.setEnabled(true);
mAutoCompleteTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
getDialog().dismiss();
return true;
}
return false;
}
});
setDialogLayoutResource(R.layout.preference_dialog_autocomplete_edittext);
}
public AutoCompleteEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public AutoCompleteEditTextPreference(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.dialogPreferenceStyle);
}
public AutoCompleteEditTextPreference(Context context) {
this(context, null);
}
public AutoCompleteTextView getAutoCompleteTextView() {
return mAutoCompleteTextView;
}
/**
* Saves the text to the {@link SharedPreferences}.
*
* @param text The text to save
*/
public void setText(String text) {
// Always persist/notify the first time.
final boolean changed = !TextUtils.equals(mText, text);
if (changed || !mTextSet) {
mText = text;
mTextSet = true;
persistString(text);
if (changed) {
notifyDependencyChange(shouldDisableDependents());
notifyChanged();
}
}
}
@VisibleForTesting
@Override
public void onClick() {
super.onClick();
}
/**
* Gets the text from the {@link SharedPreferences}.
*
* @return The current preference value.
*/
public String getText() {
return mText;
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
AutoCompleteTextView editText = mAutoCompleteTextView;
editText.setText(getText());
editText.requestFocus();
ViewParent oldParent = editText.getParent();
if (oldParent != view) {
if (oldParent != null) {
((ViewGroup) oldParent).removeView(editText);
}
onAddEditTextToDialogView(view, editText);
}
editText.setSelection(editText.getText().length());
}
/**
* Adds the AutoCompleteTextView widget of this preference to the dialog's view.
*
* @param dialogView The dialog view.
*/
protected void onAddEditTextToDialogView(View dialogView, AutoCompleteTextView editText) {
ViewGroup container = (ViewGroup) dialogView
.findViewById(R.id.autocomplete_edittext_container);
if (container != null) {
container.addView(editText, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
String value = mAutoCompleteTextView.getText().toString();
if (callChangeListener(value)) {
setText(value);
}
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setText(restoreValue ? getPersistedString(mText) : (String) defaultValue);
}
@Override
public boolean shouldDisableDependents() {
return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
}
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (isPersistent()) {
// No need to save instance state since it's persistent
return superState;
}
final SavedState myState = new SavedState(superState);
myState.text = getText();
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !state.getClass().equals(SavedState.class)) {
// Didn't save state for us in onSaveInstanceState
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
setText(myState.text);
}
private static class SavedState extends BaseSavedState {
String text;
public SavedState(Parcel source) {
super(source);
text = source.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(text);
}
public SavedState(Parcelable superState) {
super(superState);
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
/** {@link AutoCompleteTextView} that always shows the suggestions. */
private class InstantAutoCompleteTextView extends AutoCompleteTextView {
public InstantAutoCompleteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean enoughToFilter() {
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
showDropDownIfFocused();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
showDropDownIfFocused();
}
private void showDropDownIfFocused() {
if (isFocused() && getWindowVisibility() == View.VISIBLE) {
showDropDown();
}
}
}
public static class AutoCompleteEditTextPreferenceDialogFragment
extends CustomDialogPreference.CustomPreferenceDialogFragment {
public static CustomDialogPreference.CustomPreferenceDialogFragment
newInstance(String key) {
return CustomDialogPreference.CustomPreferenceDialogFragment.newInstance(key);
}
}
}