Android監聽軟鍵盤開啟收起事件
一:瞭解軟鍵盤上各類鍵名:
電話鍵
鍵名 描述 鍵值
KEYCODE_CALL 撥號鍵 5
KEYCODE_ENDCALL 掛機鍵 6
KEYCODE_HOME 按鍵Home 3
KEYCODE_MENU 選單鍵 82
KEYCODE_BACK 返回鍵 4
KEYCODE_SEARCH 搜尋鍵 84
KEYCODE_CAMERA 拍照鍵 27
KEYCODE_FOCUS 拍照對焦鍵 80
KEYCODE_POWER 電源鍵 26
KEYCODE_NOTIFICATION 通知鍵 83
KEYCODE_MUTE 話筒靜音鍵 91
KEYCODE_VOLUME_MUTE 揚聲器靜音鍵 164
KEYCODE_VOLUME_UP 音量增加鍵 24
KEYCODE_VOLUME_DOWN 音量減小鍵 25
控制鍵
鍵名 描述 鍵值
KEYCODE_ENTER 回車鍵 66
KEYCODE_ESCAPE ESC鍵 111
KEYCODE_DPAD_CENTER 導航鍵 確定鍵 23
KEYCODE_DPAD_UP 導航鍵 向上 19
KEYCODE_DPAD_DOWN 導航鍵 向下 20
KEYCODE_DPAD_LEFT 導航鍵 向左 21
KEYCODE_DPAD_RIGHT 導航鍵 向右 22
KEYCODE_MOVE_HOME 游標移動到開始鍵 122
KEYCODE_MOVE_END 游標移動到末尾鍵 123
KEYCODE_PAGE_UP 向上翻頁鍵 92
KEYCODE_PAGE_DOWN 向下翻頁鍵 93
KEYCODE_DEL 退格鍵 67
KEYCODE_FORWARD_DEL 刪除鍵 112
KEYCODE_INSERT 插入鍵 124
KEYCODE_TAB Tab鍵 61
KEYCODE_NUM_LOCK 小鍵盤鎖 143
KEYCODE_CAPS_LOCK 大寫鎖定鍵 115
KEYCODE_BREAK Break/Pause鍵 121
KEYCODE_SCROLL_LOCK 滾動鎖定鍵 116
KEYCODE_ZOOM_IN 放大鍵 168
KEYCODE_ZOOM_OUT 縮小鍵 169
二:四種收起軟鍵盤的方式
1、點選軟鍵盤右下角的Return按鈕(系統收起)
editText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) {
// 可捕捉右下角的Return按鈕
//新增丟擲收起事件程式碼
return false;
}
});
2、輸入框焦點時按返回按鈕(系統收起)
editText.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//keyCode == KeyEvent.KEYCODE_ENTER 回車鍵
//一般執行收起鍵盤操作
//...
return true;
}
return false;
}
});
開啟鍵盤和收起鍵盤程式碼:
/**
* 開啟鍵盤.
*
* @param context the context
*/
public static void showSoftInput(Context context) {
InputMethodManager inputMethodManager = (InputMethodManager) context
.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
/**
* 關閉鍵盤事件.
*
* @param context the context
*/
public static void closeSoftInput(Context context) {
InputMethodManager inputMethodManager = (InputMethodManager) context
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null && ((Activity) context).getCurrentFocus() != null) {
inputMethodManager.hideSoftInputFromWindow(((Activity) context).getCurrentFocus()
.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
3、點選軟鍵盤和輸入框的外部
給輸入框的父容器增加觸控監聽
@Override
public boolean onTouchEvent(MotionEvent event) {
if (indexOfChild(editText) > -1) {
// 新增收起鍵盤方法
}
return super.onTouchEvent(event);
}
4、點選軟鍵盤自帶的收起按鈕(軟鍵盤收起)
注:一般介面銷燬時需要移除軟鍵盤上的監聽
1)Activity:
public class SoftKeyboardActivity extends AppCompatActivity implements SoftKeyboardStateHelper.SoftKeyboardStateListener{
private SoftKeyboardStateHelper softKeyboardStateHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_soft_keyboard);
initView();
}
private void initView() {
softKeyboardStateHelper = new SoftKeyboardStateHelper(this);
softKeyboardStateHelper.addSoftKeyboardStateListener(this);
}
@Override
public void onSoftKeyboardOpened(int keyboardHeightInPx) {
Toast.makeText(SoftKeyboardActivity.this, "鍵盤開啟", Toast.LENGTH_SHORT).show();
}
@Override
public void onSoftKeyboardClosed() {
Toast.makeText(SoftKeyboardActivity.this, "鍵盤關閉", Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
softKeyboardStateHelper.removeSoftKeyboardStateListener(this);
}
}
2)佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
android:id="@+id/lin_01"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_margin="20dp"
android:orientation="horizontal">
<EditText
android:id="@+id/edit_01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginRight="8dp"
android:layout_weight="1"
android:background="@drawable/details_set_a"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:textCursorDrawable="@drawable/color_cursor" />
<!-- android:textCursorDrawable="@drawable/color_cursor" -->
<!-- 游標顏色 -->
<TextView
android:id="@+id/tv_01"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="@drawable/collection_bg02"
android:gravity="center"
android:text="新增" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
3)自定義的軟鍵盤自帶的收起:
import android.app.Activity;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import java.util.LinkedList;
import java.util.List;
/**
* 自定義軟鍵盤自帶的收起控制
* Created by ${Dota.Wang} on 2017/12/11.
*/
public class SoftKeyboardStateHelper implements ViewTreeObserver.OnGlobalLayoutListener {
private View activityRootView;
private int lastSoftKeyboardHeightInPx;
private boolean isSoftKeyboardOpened;
private int height ;//控制軟鍵盤開啟時機
public interface SoftKeyboardStateListener {
void onSoftKeyboardOpened(int keyboardHeightInPx);
void onSoftKeyboardClosed();
}
private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
public SoftKeyboardStateHelper(Activity contextObj) {
if (contextObj == null) {
Log.i("dota", "contextObj is null");
return;
}
activityRootView = findContentView(contextObj);
if (activityRootView!=null){
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
// this(activityRootView, false);
}
public SoftKeyboardStateHelper(Activity contextObj, boolean isSoftKeyboardOpened) {
if (contextObj == null) {
Log.i("dota", "contextObj is null");
return;
}
activityRootView = findContentView(contextObj);
if (activityRootView!=null){
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
// this.activityRootView = activityRootView;
// this.isSoftKeyboardOpened = isSoftKeyboardOpened;
}
private View findContentView(Activity contextObj) {
return contextObj.findViewById(android.R.id.content);
}
@Override
public void onGlobalLayout() {
final Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (screenHeight == 1920){
height = 200;
}else {
height = 100;
}
if (!isSoftKeyboardOpened && heightDiff > height ) { // if more than 100 pixels, its probably a keyboard...
isSoftKeyboardOpened = true;
notifyOnSoftKeyboardOpened(heightDiff);
} else if (isSoftKeyboardOpened && heightDiff < height ) {
isSoftKeyboardOpened = false;
notifyOnSoftKeyboardClosed();
}
}
public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
}
public boolean isSoftKeyboardOpened() {
return isSoftKeyboardOpened;
}
/**
* Default value is zero (0)
* @return last saved keyboard height in px
*/
public int getLastSoftKeyboardHeightInPx() {
return lastSoftKeyboardHeightInPx;
}
public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.add(listener);
}
public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.remove(listener);
}
private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardOpened(keyboardHeightInPx);
}
}
}
private void notifyOnSoftKeyboardClosed() {
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardClosed();
}
}
}
}
三:EditText被底部固定欄擋住,使用AndroidBug5497Workaround出現相容問題
一般這類問題出現在華為手機上比較多,如榮耀手機
解決方法如下:
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
/**
* Created by Administrator on 2017/12/8.
*/
public class AndroidBug5497Workaround {
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
public static void assistActivity (Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private AndroidBug5497Workaround(Activity activity) {
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard/4)) {
// keyboard probably just became visible
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
// keyboard probably just became hidden
frameLayoutParams.height = usableHeightSansKeyboard;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom);// 全屏模式下: return r.bottom
}
}
使用起來很容易,在你的setContentView 之後呼叫:
AndroidBug5497Workaround.assistActivity(this);
此時可能還會出現問題,可以嘗試在該Activity的AndroidManifest中新增屬性
android:windowSoftInputMode="adjustResize"