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