1 /* 2 * Copyright (C) 2015 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 package com.android.launcher3; 17 18 import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync; 19 20 import android.content.Context; 21 import android.text.TextUtils; 22 import android.util.AttributeSet; 23 import android.view.DragEvent; 24 import android.view.KeyEvent; 25 import android.view.View; 26 import android.view.inputmethod.InputMethodManager; 27 import android.widget.EditText; 28 29 import com.android.launcher3.config.FeatureFlags; 30 import com.android.launcher3.views.ActivityContext; 31 32 33 /** 34 * The edit text that reports back when the back key has been pressed. 35 * Note: AppCompatEditText doesn't fully support #displayCompletions and #onCommitCompletion 36 */ 37 public class ExtendedEditText extends EditText { 38 39 private boolean mShowImeAfterFirstLayout; 40 private boolean mForceDisableSuggestions = false; 41 42 /** 43 * Implemented by listeners of the back key. 44 */ 45 public interface OnBackKeyListener { onBackKey()46 boolean onBackKey(); 47 } 48 49 private OnBackKeyListener mBackKeyListener; 50 ExtendedEditText(Context context)51 public ExtendedEditText(Context context) { 52 // ctor chaining breaks the touch handling 53 super(context); 54 } 55 ExtendedEditText(Context context, AttributeSet attrs)56 public ExtendedEditText(Context context, AttributeSet attrs) { 57 // ctor chaining breaks the touch handling 58 super(context, attrs); 59 } 60 ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr)61 public ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr) { 62 super(context, attrs, defStyleAttr); 63 } 64 setOnBackKeyListener(OnBackKeyListener listener)65 public void setOnBackKeyListener(OnBackKeyListener listener) { 66 mBackKeyListener = listener; 67 } 68 69 @Override onKeyPreIme(int keyCode, KeyEvent event)70 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 71 // If this is a back key, propagate the key back to the listener 72 if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { 73 if (TextUtils.isEmpty(getText())) { 74 hideKeyboard(); 75 } 76 if (mBackKeyListener != null) { 77 return mBackKeyListener.onBackKey(); 78 } 79 return false; 80 } 81 return super.onKeyPreIme(keyCode, event); 82 } 83 84 @Override onDragEvent(DragEvent event)85 public boolean onDragEvent(DragEvent event) { 86 // We don't want this view to interfere with Launcher own drag and drop. 87 return false; 88 } 89 90 @Override onLayout(boolean changed, int left, int top, int right, int bottom)91 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 92 super.onLayout(changed, left, top, right, bottom); 93 if (mShowImeAfterFirstLayout) { 94 // soft input only shows one frame after the layout of the EditText happens, 95 post(() -> { 96 showSoftInput(); 97 mShowImeAfterFirstLayout = false; 98 }); 99 } 100 } 101 102 // inherited class can override to change the appearance of the edit text. show()103 public void show() {} 104 showKeyboard()105 public void showKeyboard() { 106 mShowImeAfterFirstLayout = !showSoftInput(); 107 } 108 hideKeyboard()109 public void hideKeyboard() { 110 hideKeyboardAsync(ActivityContext.lookupContext(getContext()), getWindowToken()); 111 } 112 showSoftInput()113 private boolean showSoftInput() { 114 return requestFocus() && 115 getContext().getSystemService(InputMethodManager.class) 116 .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT); 117 } 118 dispatchBackKey()119 public void dispatchBackKey() { 120 hideKeyboard(); 121 if (mBackKeyListener != null) { 122 mBackKeyListener.onBackKey(); 123 } 124 } 125 126 /** 127 * Set to true when you want isSuggestionsEnabled to return false. 128 * Use this to disable the red underlines that appear under typos when suggestions is enabled. 129 */ forceDisableSuggestions(boolean forceDisableSuggestions)130 public void forceDisableSuggestions(boolean forceDisableSuggestions) { 131 mForceDisableSuggestions = forceDisableSuggestions; 132 } 133 134 @Override isSuggestionsEnabled()135 public boolean isSuggestionsEnabled() { 136 return !mForceDisableSuggestions && super.isSuggestionsEnabled(); 137 } 138 reset()139 public void reset() { 140 if (!TextUtils.isEmpty(getText())) { 141 setText(""); 142 } 143 if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) { 144 return; 145 } 146 if (isFocused()) { 147 View nextFocus = focusSearch(View.FOCUS_DOWN); 148 if (nextFocus != null) { 149 nextFocus.requestFocus(); 150 } 151 } 152 hideKeyboard(); 153 } 154 } 155