Soft keyboard open and close listener in an activity in Android
我有一个
是否有任何监听器或回调或任何黑客攻击时,从Android上的第一个
仅当您的活动的
我为我的活动使用类似下面的基类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | public class BaseActivity extends Activity { private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight(); int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(BaseActivity.this); if(heightDiff <= contentViewTop){ onHideKeyboard(); Intent intent = new Intent("KeyboardWillHide"); broadcastManager.sendBroadcast(intent); } else { int keyboardHeight = heightDiff - contentViewTop; onShowKeyboard(keyboardHeight); Intent intent = new Intent("KeyboardWillShow"); intent.putExtra("KeyboardHeight", keyboardHeight); broadcastManager.sendBroadcast(intent); } } }; private boolean keyboardListenersAttached = false; private ViewGroup rootLayout; protected void onShowKeyboard(int keyboardHeight) {} protected void onHideKeyboard() {} protected void attachKeyboardListeners() { if (keyboardListenersAttached) { return; } rootLayout = (ViewGroup) findViewById(R.id.rootLayout); rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener); keyboardListenersAttached = true; } @Override protected void onDestroy() { super.onDestroy(); if (keyboardListenersAttached) { rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener); } } } |
以下示例活动使用此选项在键盘显示时隐藏视图,并在隐藏键盘时再次显示键盘。
xml布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rootLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > <!-- omitted for brevity --> </ScrollView> <LinearLayout android:id="@+id/bottomContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- omitted for brevity --> </LinearLayout> </LinearLayout> |
活动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class TestActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); attachKeyboardListeners(); } @Override protected void onShowKeyboard(int keyboardHeight) { // do things when keyboard is shown bottomContainer.setVisibility(View.GONE); } @Override protected void onHideKeyboard() { // do things when keyboard is hidden bottomContainer.setVisibility(View.VISIBLE); } } |
一块蛋糕与令人敬畏
KeyboardVisibilityEvent库
1 2 3 4 5 6 7 8 | KeyboardVisibilityEvent.setEventListener( getActivity(), new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean isOpen) { // write your code } }); |
Yasuhiro SHIMIZU的积分
正如维克拉姆在评论中指出的那样,检测软键盘是否显示或已经消失只能通过一些丑陋的黑客攻击。
也许在edittext上设置焦点监听器就足够了:
1 2 3 4 5 6 7 8 9 10 | yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { //got focus } else { //lost focus } } }); |
对于活动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); activityRootView.getWindowVisibleDisplayFrame(r); int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top); if (heightDiff > 100) { //enter your code here }else{ //enter code for hid } } }); |
片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | view = inflater.inflate(R.layout.live_chat_fragment, null); view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. view.getWindowVisibleDisplayFrame(r); int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top); if (heightDiff > 500) { // if more than 100 pixels, its probably a keyboard... } } }); |
Jaap的答案不适用于AppCompatActivity。而是获取状态栏和导航栏等的高度,并与您的应用程序的窗口大小进行比较。
像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // navigation bar height int navigationBarHeight = 0; int resourceId = getResources().getIdentifier("navigation_bar_height","dimen","android"); if (resourceId > 0) { navigationBarHeight = getResources().getDimensionPixelSize(resourceId); } // status bar height int statusBarHeight = 0; resourceId = getResources().getIdentifier("status_bar_height","dimen","android"); if (resourceId > 0) { statusBarHeight = getResources().getDimensionPixelSize(resourceId); } // display window size for the app layout Rect rect = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); // screen height - (user app height + status + nav) ..... if non-zero, then there is a soft keyboard int keyboardHeight = rootLayout.getRootView().getHeight() - (statusBarHeight + navigationBarHeight + rect.height()); if (keyboardHeight <= 0) { onHideKeyboard(); } else { onShowKeyboard(keyboardHeight); } } }; |
你可以尝试一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | private void initKeyBoardListener() { // Минимальное значение клавиатуры. // Threshold for minimal keyboard height. final int MIN_KEYBOARD_HEIGHT_PX = 150; // Окно верхнего уровня view. // Top-level window decor view. final View decorView = getWindow().getDecorView(); // Регистрируем глобальный слушатель. Register global layout listener. decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { // Видимый прямоугольник внутри окна. // Retrieve visible rectangle inside window. private final Rect windowVisibleDisplayFrame = new Rect(); private int lastVisibleDecorViewHeight; @Override public void onGlobalLayout() { decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame); final int visibleDecorViewHeight = windowVisibleDisplayFrame.height(); if (lastVisibleDecorViewHeight != 0) { if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) { Log.d("Pasha","SHOW"); } else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) { Log.d("Pasha","HIDE"); } } // Сохраняем текущую высоту view до следующего вызова. // Save current decor view height for the next call. lastVisibleDecorViewHeight = visibleDecorViewHeight; } }); } |
您可以使用我的Rx扩展功能(Kotlin)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /** * @return [Observable] to subscribe of keyboard visibility changes. */ fun AppCompatActivity.keyboardVisibilityChanges(): Observable<Boolean> { // flag indicates whether keyboard is open var isKeyboardOpen = false val notifier: BehaviorSubject<Boolean> = BehaviorSubject.create() // approximate keyboard height val approximateKeyboardHeight = dip(100) // device screen height val screenHeight: Int = getScreenHeight() val visibleDisplayFrame = Rect() val viewTreeObserver = window.decorView.viewTreeObserver val onDrawListener = ViewTreeObserver.OnDrawListener { window.decorView.getWindowVisibleDisplayFrame(visibleDisplayFrame) val keyboardHeight = screenHeight - (visibleDisplayFrame.bottom - visibleDisplayFrame.top) val keyboardOpen = keyboardHeight >= approximateKeyboardHeight val hasChanged = isKeyboardOpen xor keyboardOpen if (hasChanged) { isKeyboardOpen = keyboardOpen notifier.onNext(keyboardOpen) } } val lifeCycleObserver = object : GenericLifecycleObserver { override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event?) { if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) { viewTreeObserver.removeOnDrawListener(onDrawListener) source.lifecycle.removeObserver(this) notifier.onComplete() } } } viewTreeObserver.addOnDrawListener(onDrawListener) lifecycle.addObserver(lifeCycleObserver) return notifier .doOnDispose { viewTreeObserver.removeOnDrawListener(onDrawListener) lifecycle.removeObserver(lifeCycleObserver) } .onTerminateDetach() .hide() } |
例:
1 2 3 4 5 | (context as AppCompatActivity) .keyboardVisibilityChanges() .subscribeBy { isKeyboardOpen -> // your logic } |
使用这个班,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; public class SoftKeyboard implements View.OnFocusChangeListener { private static final int CLEAR_FOCUS = 0; private ViewGroup layout; private int layoutBottom; private InputMethodManager im; private int[] coords; private boolean isKeyboardShow; private SoftKeyboardChangesThread softKeyboardThread; private List<EditText> editTextList; private View tempView; // reference to a focused EditText public SoftKeyboard(ViewGroup layout, InputMethodManager im) { this.layout = layout; keyboardHideByDefault(); initEditTexts(layout); this.im = im; this.coords = new int[2]; this.isKeyboardShow = false; this.softKeyboardThread = new SoftKeyboardChangesThread(); this.softKeyboardThread.start(); } public void openSoftKeyboard() { if(!isKeyboardShow) { layoutBottom = getLayoutCoordinates(); im.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT); softKeyboardThread.keyboardOpened(); isKeyboardShow = true; } } public void closeSoftKeyboard() { if(isKeyboardShow) { im.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); isKeyboardShow = false; } } public void setSoftKeyboardCallback(SoftKeyboardChanged mCallback) { softKeyboardThread.setCallback(mCallback); } public void unRegisterSoftKeyboardCallback() { softKeyboardThread.stopThread(); } public interface SoftKeyboardChanged { public void onSoftKeyboardHide(); public void onSoftKeyboardShow(); } private int getLayoutCoordinates() { layout.getLocationOnScreen(coords); return coords[1] + layout.getHeight(); } private void keyboardHideByDefault() { layout.setFocusable(true); layout.setFocusableInTouchMode(true); } /* * InitEditTexts now handles EditTexts in nested views * Thanks to Francesco Verheye ([email protected]) */ private void initEditTexts(ViewGroup viewgroup) { if(editTextList == null) editTextList = new ArrayList<EditText>(); int childCount = viewgroup.getChildCount(); for(int i=0; i<= childCount-1;i++) { View v = viewgroup.getChildAt(i); if(v instanceof ViewGroup) { initEditTexts((ViewGroup) v); } if(v instanceof EditText) { EditText editText = (EditText) v; editText.setOnFocusChangeListener(this); editText.setCursorVisible(true); editTextList.add(editText); } } } /* * OnFocusChange does update tempView correctly now when keyboard is still shown * Thanks to Israel Dominguez ([email protected]) */ @Override public void onFocusChange(View v, boolean hasFocus) { if(hasFocus) { tempView = v; if(!isKeyboardShow) { layoutBottom = getLayoutCoordinates(); softKeyboardThread.keyboardOpened(); isKeyboardShow = true; } } } // This handler will clear focus of selected EditText private final Handler mHandler = new Handler() { @Override public void handleMessage(Message m) { switch(m.what) { case CLEAR_FOCUS: if(tempView != null) { tempView.clearFocus(); tempView = null; } break; } } }; private class SoftKeyboardChangesThread extends Thread { private AtomicBoolean started; private SoftKeyboardChanged mCallback; public SoftKeyboardChangesThread() { started = new AtomicBoolean(true); } public void setCallback(SoftKeyboardChanged mCallback) { this.mCallback = mCallback; } @Override public void run() { while(started.get()) { // Wait until keyboard is requested to open synchronized(this) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int currentBottomLocation = getLayoutCoordinates(); // There is some lag between open soft-keyboard function and when it really appears. while(currentBottomLocation == layoutBottom && started.get()) { currentBottomLocation = getLayoutCoordinates(); } if(started.get()) mCallback.onSoftKeyboardShow(); // When keyboard is opened from EditText, initial bottom location is greater than layoutBottom // and at some moment equals layoutBottom. // That broke the previous logic, so I added this new loop to handle this. while(currentBottomLocation >= layoutBottom && started.get()) { currentBottomLocation = getLayoutCoordinates(); } // Now Keyboard is shown, keep checking layout dimensions until keyboard is gone while(currentBottomLocation != layoutBottom && started.get()) { synchronized(this) { try { wait(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } currentBottomLocation = getLayoutCoordinates(); } if(started.get()) mCallback.onSoftKeyboardHide(); // if keyboard has been opened clicking and EditText. if(isKeyboardShow && started.get()) isKeyboardShow = false; // if an EditText is focused, remove its focus (on UI thread) if(started.get()) mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget(); } } public void keyboardOpened() { synchronized(this) { notify(); } } public void stopThread() { synchronized(this) { started.set(false); notify(); } } } } |
在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /* Somewhere else in your code */ RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use the layout root InputMethodManager im = (InputMethodManager)getSystemService(Service.INPUT_METHOD_SERVICE); /* Instantiate and pass a callback */ SoftKeyboard softKeyboard; softKeyboard = new SoftKeyboard(mainLayout, im); softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged() { @Override public void onSoftKeyboardHide() { // Code here } @Override public void onSoftKeyboardShow() { // Code here } }); /* Open or close the soft keyboard easily */ softKeyboard.openSoftKeyboard(); softKeyboard.closeSoftKeyboard(); /* Prevent memory leaks:*/ @Override public void onDestroy() { super.onDestroy(); softKeyboard.unRegisterSoftKeyboardCallback(); } |
P.S - 完全从这里开始。
软键盘监听器的不同实现,不依赖于窗口调整&amp;因此在多窗口世界中也能很好地工作。它当然有它自己的怪癖,但是它们与多窗口和窗口大小检测在一起的完全破碎相比毫无意义。
https://github.com/sqrt1764/AndroidSoftKeyboardListener
希望改进的想法!
您可以通过覆盖Activity中的两个方法来处理键盘可见性:
如果可以,尝试扩展EditText并覆盖'onKeyPreIme'方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Override public void setOnEditorActionListener(final OnEditorActionListener listener) { mEditorListener = listener; //keep it for later usage super.setOnEditorActionListener(listener); } @Override public boolean onKeyPreIme(final int keyCode, final KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mEditorListener != null) { //you can define and use custom listener, //OR define custom R.id.<imeId> //OR check event.keyCode in listener impl //* I used editor action because of ButterKnife @ mEditorListener.onEditorAction(this, android.R.id.closeButton, event); } } return super.onKeyPreIme(keyCode, event); } |
你怎么能扩展它:
我认为,如前所述,重新计算屏幕高度不是100%成功。
要明确的是,"onKeyPreIme"的覆盖不会在"隐藏软键盘编程"方法中调用,但是如果你在任何地方都这样做,你应该在那里做'onKeyboardHidden'逻辑,而不是创建一个全面的解决方案。
另一种方法是检查用户何时停止输入...
当TextEdit处于焦点(用户正在/正在键入)时,您可以隐藏视图(焦点侦听器)
并使用Handler + Runnable和文本更改侦听器来关闭键盘(无论其可见性如何)并在一段延迟后显示视图。
需要注意的主要问题是您使用的延迟,这取决于这些TextEdits的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | Handler timeoutHandler = new Handler(); Runnable typingRunnable = new Runnable() { public void run() { // current TextEdit View view = getCurrentFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // reset focus view.clearFocus(); // close keyboard (whether its open or not) imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN); // SET VIEWS VISIBLE } }; editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { // SET VIEWS GONE // reset handler timeoutHandler.removeCallbacks(typingRunnable); timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT); } } }); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Reset Handler... timeoutHandler.removeCallbacks(typingRunnable); } @Override public void afterTextChanged(Editable s) { // Reset Handler Cont. if (editText.getText().toString().trim().length() > 0) { timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT); } } }); |
以下代码对我有用,
1 2 3 4 5 6 7 8 9 10 11 12 13 | mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mainLayout != null) { int heightDiff = mainLayout.getRootView().getHeight() - mainLayout.getHeight(); if (heightDiff > dpToPx(getActivity(), 200)) { //keyboard is open } else { //keyboard is hide } } } }); |
对于
这是我的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { private int contentDiff; private int rootHeight; @Override public void onGlobalLayout() { View contentView = getWindow().findViewById(Window.ID_ANDROID_CONTENT); if (rootHeight != mDrawerLayout.getRootView().getHeight()) { rootHeight = mDrawerLayout.getRootView().getHeight(); contentDiff = rootHeight - contentView.getHeight(); return; } int newContentDiff = rootHeight - contentView.getHeight(); if (contentDiff != newContentDiff) { if (contentDiff < newContentDiff) { onShowKeyboard(newContentDiff - contentDiff); } else { onHideKeyboard(); } contentDiff = newContentDiff; } } }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | private boolean isKeyboardShown = false; private int prevContentHeight = 0; private ViewGroup contentLayout; private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int contentHeight = contentLayout.getHeight(); int rootViewHeight = contentLayout.getRootView().getHeight(); if (contentHeight > 0) { if (!isKeyboardShown) { if (contentHeight < prevContentHeight) { isKeyboardShown = true; onShowKeyboard(rootViewHeight - contentHeight); } } else { if (contentHeight > prevContentHeight) { isKeyboardShown = false; onHideKeyboard(); } } prevContentHeight = contentHeight; } } }; |
我已经修改了Jaap接受的答案了。但在我的情况下,很少有假设,如
对我来说,到目前为止它已经很好地工作了。我希望它也适用于其他人。
当键盘显示
1 | rootLayout.getHeight() < rootLayout.getRootView().getHeight() - getStatusBarHeight() |
是真的,否则隐藏
"Jaap van Hengstum"的答案对我有用,但没有必要像他刚才说的那样设置"android:windowSoftInputMode"!
我把它缩小了(它现在只是检测我想要的东西,实际上是显示和隐藏键盘的事件):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight(); int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); if(heightDiff <= contentViewTop){ onHideKeyboard(); } else { onShowKeyboard(); } } }; private boolean keyboardListenersAttached = false; private ViewGroup rootLayout; protected void onShowKeyboard() {} protected void onHideKeyboard() {} protected void attachKeyboardListeners() { if (keyboardListenersAttached) { return; } rootLayout = (ViewGroup) findViewById(R.id.CommentsActivity); rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener); keyboardListenersAttached = true; } @Override protected void onDestroy() { super.onDestroy(); if (keyboardListenersAttached) { rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener); } } |
并且不要忘记添加这个
1 2 3 4 | protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_comments); attachKeyboardListeners();} |
这段代码非常好用
将此类用于根视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | public class KeyboardConstraintLayout extends ConstraintLayout { private KeyboardListener keyboardListener; private EditText targetEditText; private int minKeyboardHeight; private boolean isShow; public KeyboardConstraintLayout(Context context) { super(context); minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); //128dp } public KeyboardConstraintLayout(Context context, AttributeSet attrs) { super(context, attrs); minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp } public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!isInEditMode()) { Activity activity = (Activity) getContext(); @SuppressLint("DrawAllocation") Rect rect = new Rect(); getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight; if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) { if (keyboardHeight > minKeyboardHeight) { if (!isShow) { isShow = true; keyboardListener.onKeyboardVisibility(true); } }else { if (isShow) { isShow = false; keyboardListener.onKeyboardVisibility(false); } } } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public boolean isShowKeyboard() { return isShow; } public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) { this.targetEditText = targetEditText; this.keyboardListener = keyboardListener; } public interface KeyboardListener { void onKeyboardVisibility (boolean isVisible); } |
}
并在activity或fragment中设置键盘侦听器:
1 2 3 4 5 6 | rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() { @Override public void onKeyboardVisibility(boolean isVisible) { } }); |
这将无需更改您的活动的
第1步:扩展EditText类并覆盖这两个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Override public void setOnEditorActionListener(final OnEditorActionListener listener) { mEditorListener = listener; super.setOnEditorActionListener(listener); } @Override public boolean onKeyPreIme(final int keyCode, final KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mEditorListener != null) { mEditorListener.onEditorAction(this, android.R.id.closeButton, event); } } return super.onKeyPreIme(keyCode, event); } |
第2步:在您的活动中创建这两个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private void initKeyboard() { final AppEditText editText = findViewById(R.id.some_id); editText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { setKeyboard(hasFocus); } }); editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (event == null || event.getKeyCode() == KeyEvent.KEYCODE_BACK) { editText.clearFocus(); } return false; } }); } public void setKeyboard(boolean isShowing) { // do something } |
***请记住,为了使
1 2 | setFocusableInTouchMode(true); setFocusable(true); |
不幸的是,我没有足够的声誉来评论Jaap van Hengstum的回答。但是我读了一些人的评论,问题是
我有同样的问题,并找出了我遇到的问题。我使用
这不符合要求......
...已经看到许多使用尺寸计算来检查......
我想确定它是否打开,我找到
所以这真的没有回答这个问题,因为它没有解决开放或关闭更像是打开或关闭所以它是相关的代码,可以帮助其他人在各种场景...
在一项活动中
1 2 3 4 5 | if (((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) { Log.d(TAG,"Software Keyboard was shown"); } else { Log.d(TAG,"Software Keyboard was not shown"); } |
在片段中
1 2 3 4 5 6 | if (((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) { Log.d(TAG,"Software Keyboard was shown"); } else { Log.d(TAG,"Software Keyboard was not shown"); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mainactivity); attachKeyboardListeners(); .... yourEditText1.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { yourEditText2.setVisibility(View.GONE); yourEditText3.setVisibility(View.GONE); yourEditText4.setVisibility(View.GONE); yourEditText5.setVisibility(View.GONE); } else { yourEditText2.setVisibility(View.VISIBLE); yourEditText3.setVisibility(View.VISIBLE); yourEditText4.setVisibility(View.VISIBLE); yourEditText5.setVisibility(VISIBLE); } } }); } } |