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"

如果在添加完该属性还会出现全屏和adjustResize的冲突,就尝试用Plan B

完美解决问题 兼容多种手机

参考文档:

http://blog.csdn.net/lixiang_y/article/details/73743225
http://blog.csdn.net/plq690816/article/details/51374883
https://www.cnblogs.com/ldq2016/p/6223294.html

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值