史上最全:安卓监听软键盘打开或者关闭

史上最全:安卓监听软键盘打开或者关闭

SoftKeyboard open and close listener in an activity in Android?

问题:我有一个Activity,里面有5个EditText。当用户点击第一个EditText,软键盘打来,然后可以输入一些值。我翔在软件版打开的时候,设置其他View的不可见,当软键盘关闭的时候其他View课件。

说白了就是对软键盘的事件进行更新。

到底安卓立有没有类似的listener或者callback甚至是一些技巧呢?

我总结了一下一共有3中方法,期中又简单也有复杂的。

方法1

对于某些场景,可以使用一些比较丑陋的代码,但也可以算是黑科技。

可能为你的EditText**设置焦点监听**就足够了

yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {if (hasFocus) {//got focus} else {//lost focus}}
});

方法2

下面的方法只有在你的清单文件中,把Activity的android:windowSoftInputMode 属性设置为adjustResize 才有用。你可以使用Layout listener去观察你的根布局的大小是否改变。

首先你要创建一个BaseAvtivity

public class BaseActivity extends Activity {private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic 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;}@Overrideprotected void onDestroy() {super.onDestroy();if (keyboardListenersAttached) {rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);}}
}

让你的Activity继承BaseActivity

public class TestActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test_activity);attachKeyboardListeners();}@Overrideprotected void onShowKeyboard(int keyboardHeight) {// do things when keyboard is shownbottomContainer.setVisibility(View.GONE);}@Overrideprotected void onHideKeyboard() {// do things when keyboard is hiddenbottomContainer.setVisibility(View.VISIBLE);}        
}

方法3

Android给你提供的大量的api,这些api提供的大量可以重写的方法,这些方法涵盖了你可能遇到的大量的时间。所以说大部分时间你都不用去担心。但soft ketyboard并不是这样。它可以轻松的展示或者隐藏,但没有方法去监听它。下面是一个解决方案。

创建一个SoftKeyboard

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 editTextList;private View tempView; // reference to a focused EditTextpublic 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 处理嵌套在view里的edittext* 感谢 Francesco Verheye (verheye.francesco@gmail.com)*/private void initEditTexts(ViewGroup viewgroup) {if(editTextList == null)editTextList = new ArrayList();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);}}}/** 当keyboard展示的时候,OnFocusChange 更新 tempView  * Thanks to Israel Dominguez (dominguez.israel@gmail.com)*/@Overridepublic void onFocusChange(View v, boolean hasFocus) {if(hasFocus) {tempView = v;if(!isKeyboardShow) {layoutBottom = getLayoutCoordinates();softKeyboardThread.keyboardOpened();isKeyboardShow = true;}}}// 将会取消Edittext的焦点private final Handler mHandler = new Handler(){@Overridepublic 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;}@Overridepublic void run(){while(started.get()){// 等待,知道软键盘请求打卡synchronized(this){try {wait();} catch (InterruptedException e) {e.printStackTrace();}}int currentBottomLocation = getLayoutCoordinates();// 在调用打开软键盘函数和真正显示,有一些时间差while(currentBottomLocation == layoutBottom && started.get()){currentBottomLocation = getLayoutCoordinates();}if(started.get())mCallback.onSoftKeyboardShow();// 当键盘打开,出事下底部的位置比layoutBottom更好 // 在有些情况下等价于layoutBottom// 这会破坏之前的逻辑,所以我加上新的循环while(currentBottomLocation >= layoutBottom && started.get()){currentBottomLocation = getLayoutCoordinates();}// 现在键盘已经显示,继续检查Layout的尺寸,直到键盘关闭while(currentBottomLocation != layoutBottom && started.get()){synchronized(this){try {wait(500);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}currentBottomLocation = getLayoutCoordinates();}if(started.get())mCallback.onSoftKeyboardHide();// 如果 keyboard 已经打开if(isKeyboardShow && started.get())isKeyboardShow = false;// 如果一个EditText获得焦点,移除它焦点(在UI县城中)if(started.get())mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget();}   }public void keyboardOpened(){synchronized(this){notify();}}public void stopThread(){synchronized(this){started.set(false);notify();}}}
}

下面是简单的一个例子

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()
{@Overridepublic void onSoftKeyboardHide() {// Code here}@Overridepublic 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();
}

希望对你有帮助

参考自stackoverflow,以及felhr


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部