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 17 package androidx.leanback.preference; 18 19 import android.content.Context; 20 import android.os.Bundle; 21 import android.text.InputType; 22 import android.text.TextUtils; 23 import android.util.TypedValue; 24 import android.view.ContextThemeWrapper; 25 import android.view.KeyEvent; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.view.inputmethod.EditorInfo; 30 import android.view.inputmethod.InputMethodManager; 31 import android.widget.EditText; 32 import android.widget.TextView; 33 34 import androidx.preference.DialogPreference; 35 import androidx.preference.EditTextPreference; 36 37 import org.jspecify.annotations.NonNull; 38 39 /** 40 * Implemented a dialog to input text. 41 */ 42 public class LeanbackEditTextPreferenceDialogFragmentCompat extends 43 LeanbackPreferenceDialogFragmentCompat { 44 45 public static final String EXTRA_INPUT_TYPE = "input_type"; 46 public static final String EXTRA_IME_OPTIONS = "ime_option"; 47 48 private static final int DEFAULT_INPUT_TYPE = InputType.TYPE_CLASS_TEXT; 49 private static final int DEFAULT_IME_OPTIONS = EditorInfo.IME_ACTION_GO; 50 51 private static final String SAVE_STATE_TITLE = "LeanbackEditPreferenceDialog.title"; 52 private static final String SAVE_STATE_MESSAGE = "LeanbackEditPreferenceDialog.message"; 53 private static final String SAVE_STATE_TEXT = "LeanbackEditPreferenceDialog.text"; 54 private static final String SAVE_STATE_INPUT_TYPE = "LeanbackEditPreferenceDialog.inputType"; 55 private static final String SAVE_STATE_IME_OPTIONS = "LeanbackEditPreferenceDialog.imeOptions"; 56 57 private CharSequence mDialogTitle; 58 private CharSequence mDialogMessage; 59 private CharSequence mText; 60 private int mImeOptions; 61 private int mInputType; 62 63 /** 64 * Create a new LeanbackListPreferenceDialogFragmentCompat. 65 * @param key The key of {@link EditTextPreference} it will be created from. 66 * @return A new LeanbackEditTextPreferenceDialogFragmentCompat to display. 67 */ newInstance(String key)68 public static LeanbackEditTextPreferenceDialogFragmentCompat newInstance(String key) { 69 final Bundle args = new Bundle(1); 70 args.putString(ARG_KEY, key); 71 72 final LeanbackEditTextPreferenceDialogFragmentCompat 73 fragment = new LeanbackEditTextPreferenceDialogFragmentCompat(); 74 fragment.setArguments(args); 75 76 return fragment; 77 } 78 79 @Override onCreate(Bundle savedInstanceState)80 public void onCreate(Bundle savedInstanceState) { 81 super.onCreate(savedInstanceState); 82 83 if (savedInstanceState == null) { 84 final DialogPreference preference = getPreference(); 85 mDialogTitle = preference.getDialogTitle(); 86 mDialogMessage = preference.getDialogMessage(); 87 if (preference instanceof EditTextPreference) { 88 mDialogTitle = preference.getDialogTitle(); 89 mDialogMessage = preference.getDialogMessage(); 90 mText = ((EditTextPreference) preference).getText(); 91 mInputType = preference.getExtras().getInt(EXTRA_INPUT_TYPE, DEFAULT_INPUT_TYPE); 92 mImeOptions = preference.getExtras().getInt(EXTRA_IME_OPTIONS, DEFAULT_IME_OPTIONS); 93 } else { 94 throw new IllegalArgumentException("Preference must be a EditTextPreference"); 95 } 96 } else { 97 mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE); 98 mDialogMessage = savedInstanceState.getCharSequence(SAVE_STATE_MESSAGE); 99 mText = savedInstanceState.getCharSequence(SAVE_STATE_TEXT); 100 mInputType = savedInstanceState.getInt(SAVE_STATE_INPUT_TYPE, DEFAULT_INPUT_TYPE); 101 mImeOptions = savedInstanceState.getInt(SAVE_STATE_IME_OPTIONS, DEFAULT_IME_OPTIONS); 102 } 103 } 104 105 @Override onSaveInstanceState(@onNull Bundle outState)106 public void onSaveInstanceState(@NonNull Bundle outState) { 107 super.onSaveInstanceState(outState); 108 outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle); 109 outState.putCharSequence(SAVE_STATE_MESSAGE, mDialogMessage); 110 outState.putCharSequence(SAVE_STATE_TEXT, mText); 111 outState.putInt(SAVE_STATE_INPUT_TYPE, mInputType); 112 outState.putInt(SAVE_STATE_IME_OPTIONS, mImeOptions); 113 } 114 115 @Override onCreateView(@onNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)116 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, 117 Bundle savedInstanceState) { 118 TypedValue tv = new TypedValue(); 119 getActivity().getTheme().resolveAttribute( 120 androidx.preference.R.attr.preferenceTheme, tv, true); 121 int theme = tv.resourceId; 122 if (theme == 0) { 123 // Fallback to default theme. 124 theme = R.style.PreferenceThemeOverlayLeanback; 125 } 126 Context styledContext = new ContextThemeWrapper(getActivity(), theme); 127 LayoutInflater styledInflater = inflater.cloneInContext(styledContext); 128 View view = styledInflater.inflate(R.layout.leanback_edit_preference_fragment, 129 container, false); 130 131 if (!TextUtils.isEmpty(mDialogTitle)) { 132 TextView titleView = (TextView) view.findViewById(R.id.decor_title); 133 titleView.setText(mDialogTitle); 134 } 135 136 if (!TextUtils.isEmpty(mDialogMessage)) { 137 TextView messageView = (TextView) view.findViewById(android.R.id.message); 138 messageView.setVisibility(View.VISIBLE); 139 messageView.setText(mDialogMessage); 140 } 141 142 EditText editText = view.findViewById(android.R.id.edit); 143 editText.setInputType(mInputType); 144 editText.setImeOptions(mImeOptions); 145 if (!TextUtils.isEmpty(mText)) { 146 editText.setText(mText); 147 } 148 editText.setOnEditorActionListener(new EditText.OnEditorActionListener() { 149 @Override 150 public boolean onEditorAction(TextView textView, int actionId, KeyEvent event) { 151 if (actionId == EditorInfo.IME_ACTION_DONE 152 || actionId == EditorInfo.IME_ACTION_GO 153 || actionId == EditorInfo.IME_ACTION_SEARCH 154 || actionId == EditorInfo.IME_ACTION_NEXT 155 || actionId == EditorInfo.IME_ACTION_SEND) { 156 InputMethodManager imm = (InputMethodManager) 157 getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); 158 imm.hideSoftInputFromWindow(textView.getWindowToken(), 0); 159 EditTextPreference preference = (EditTextPreference) getPreference(); 160 preference.setText(textView.getText().toString()); 161 getFragmentManager().popBackStack(); 162 return true; 163 } 164 return false; 165 } 166 }); 167 168 return view; 169 } 170 171 @Override onStart()172 public void onStart() { 173 super.onStart(); 174 EditText editText = getView().findViewById(android.R.id.edit); 175 InputMethodManager imm = (InputMethodManager) 176 getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); 177 editText.requestFocus(); 178 imm.showSoftInput(editText, 0); 179 } 180 } 181