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.logging.KeyboardStateManager.KeyboardState.SHOW; 19 20 import android.content.Context; 21 import android.graphics.Rect; 22 import android.text.TextUtils; 23 import android.util.AttributeSet; 24 import android.view.DragEvent; 25 import android.view.KeyEvent; 26 import android.view.inputmethod.InputMethodManager; 27 import android.widget.EditText; 28 29 import com.android.launcher3.views.ActivityContext; 30 31 import java.util.HashSet; 32 import java.util.Set; 33 34 35 /** 36 * The edit text that reports back when the back key has been pressed. 37 * Note: AppCompatEditText doesn't fully support #displayCompletions and #onCommitCompletion 38 */ 39 public class ExtendedEditText extends EditText { 40 private final Set<OnFocusChangeListener> mOnFocusChangeListeners = new HashSet<>(); 41 42 private boolean mForceDisableSuggestions = false; 43 44 /** 45 * Implemented by listeners of the back key. 46 */ 47 public interface OnBackKeyListener { onBackKey()48 boolean onBackKey(); 49 } 50 51 private OnBackKeyListener mBackKeyListener; 52 ExtendedEditText(Context context)53 public ExtendedEditText(Context context) { 54 // ctor chaining breaks the touch handling 55 super(context); 56 } 57 ExtendedEditText(Context context, AttributeSet attrs)58 public ExtendedEditText(Context context, AttributeSet attrs) { 59 // ctor chaining breaks the touch handling 60 super(context, attrs); 61 } 62 ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr)63 public ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr) { 64 super(context, attrs, defStyleAttr); 65 } 66 setOnBackKeyListener(OnBackKeyListener listener)67 public void setOnBackKeyListener(OnBackKeyListener listener) { 68 mBackKeyListener = listener; 69 } 70 71 @Override onKeyPreIme(int keyCode, KeyEvent event)72 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 73 // If this is a back key, propagate the key back to the listener 74 if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { 75 if (TextUtils.isEmpty(getText())) { 76 hideKeyboard(); 77 } 78 if (mBackKeyListener != null) { 79 return mBackKeyListener.onBackKey(); 80 } 81 return false; 82 } 83 return super.onKeyPreIme(keyCode, event); 84 } 85 86 @Override onDragEvent(DragEvent event)87 public boolean onDragEvent(DragEvent event) { 88 // We don't want this view to interfere with Launcher own drag and drop. 89 return false; 90 } 91 showKeyboard()92 public void showKeyboard() { 93 onKeyboardShown(); 94 showSoftInput(); 95 } 96 hideKeyboard()97 public void hideKeyboard() { 98 ActivityContext.lookupContext(getContext()).hideKeyboard(); 99 clearFocus(); 100 } 101 onKeyboardShown()102 protected void onKeyboardShown() { 103 ActivityContext.lookupContext(getContext()).getStatsLogManager() 104 .keyboardStateManager().setKeyboardState(SHOW); 105 } 106 showSoftInput()107 private boolean showSoftInput() { 108 return requestFocus() && 109 getContext().getSystemService(InputMethodManager.class) 110 .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT); 111 } 112 dispatchBackKey()113 public void dispatchBackKey() { 114 hideKeyboard(); 115 if (mBackKeyListener != null) { 116 mBackKeyListener.onBackKey(); 117 } 118 } 119 120 /** 121 * Set to true when you want isSuggestionsEnabled to return false. 122 * Use this to disable the red underlines that appear under typos when suggestions is enabled. 123 */ forceDisableSuggestions(boolean forceDisableSuggestions)124 public void forceDisableSuggestions(boolean forceDisableSuggestions) { 125 mForceDisableSuggestions = forceDisableSuggestions; 126 } 127 128 @Override isSuggestionsEnabled()129 public boolean isSuggestionsEnabled() { 130 return !mForceDisableSuggestions && super.isSuggestionsEnabled(); 131 } 132 reset()133 public void reset() { 134 if (!TextUtils.isEmpty(getText())) { 135 setText(""); 136 } 137 } 138 139 /** 140 * This method should be preferred to {@link #setOnFocusChangeListener(OnFocusChangeListener)}, 141 * as it allows for multiple listeners from different sources. 142 */ addOnFocusChangeListener(OnFocusChangeListener listener)143 public void addOnFocusChangeListener(OnFocusChangeListener listener) { 144 mOnFocusChangeListeners.add(listener); 145 } 146 147 /** 148 * Removes the given listener from the set of registered focus listeners, or does nothing if it 149 * wasn't registered in the first place. 150 */ removeOnFocusChangeListener(OnFocusChangeListener listener)151 public void removeOnFocusChangeListener(OnFocusChangeListener listener) { 152 mOnFocusChangeListeners.remove(listener); 153 } 154 155 @Override onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect)156 protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 157 super.onFocusChanged(focused, direction, previouslyFocusedRect); 158 for (OnFocusChangeListener listener : mOnFocusChangeListeners) { 159 listener.onFocusChange(this, focused); 160 } 161 } 162 163 /** 164 * Save the input, suggestion, hint states when it's on focus, and set to unfocused states. 165 */ saveFocusedStateAndUpdateToUnfocusedState()166 public void saveFocusedStateAndUpdateToUnfocusedState() {} 167 168 /** 169 * Restore to the previous saved focused state. 170 */ restoreToFocusedState()171 public void restoreToFocusedState() {} 172 } 173