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