android监听键盘

android中的带有输入功能的页面布局经常被弹出的键盘遮挡,一种处理方法是监听键盘的弹出,设置布局的padding或隐藏某些占位控件,使得输入框不被键盘遮挡。一种常用的方法是当Activity设置为android:windowSoftInputMode="adjustResize"的时候,键盘的弹出和隐藏会触发onSizeChaged的事件,用下面的自定义RealativeLayout则能监听这个函数并判断键盘是弹出还是收起。

/*
 * @Project: GZJK
 * @Author: cmcc
 * @Date: 2015年5月6日
 * @Copyright: 2000-2015 CMCC . All rights reserved.
 */
package com.matrix.appsdk.widget.keyboard;

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Display;
import android.widget.RelativeLayout;

/**
* @ClassName: InputMethodRelativeLayout
* @Description: 监听键盘的现实和隐藏,Activity设置为adjustResize,非全屏
* @author
* @date 2015年5月6日 下午6:48:57
*/
public class InputMethodRelativeLayout extends RelativeLayout {
    private int width;
    protected OnSizeChangedListenner onSizeChangedListenner;
    private boolean sizeChanged = false; // 变化的标志
    private int height;
    private int screenHeight; // 屏幕高度

    public InputMethodRelativeLayout(Context paramContext, AttributeSet paramAttributeSet) {
        super(paramContext, paramAttributeSet);
        Display localDisplay = ((Activity)paramContext).getWindowManager().getDefaultDisplay();
        this.screenHeight = localDisplay.getHeight();
    }

    public InputMethodRelativeLayout(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {
        super(paramContext, paramAttributeSet, paramInt);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        this.width = widthMeasureSpec;
        this.height = heightMeasureSpec;
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    public void onSizeChanged(int w, int h, int oldw, int oldh) {
        // 监听不为空、宽度不变、当前高度与历史高度不为0
        if ((this.onSizeChangedListenner != null) && (w == oldw) && (oldw != 0) && (oldh != 0)) {
            if ((h >= oldh) || (Math.abs(h - oldh) <= 1 * this.screenHeight / 4)) {
                if ((h <= oldh) || (Math.abs(h - oldh) <= 1 * this.screenHeight / 4))
                    return;
                this.sizeChanged = false;
            } else {
                this.sizeChanged = true;
            }
            this.onSizeChangedListenner.onSizeChange(this.sizeChanged, oldh, h);
            measure(this.width - w + getWidth(), this.height - h + getHeight());
        }
    }

    /**
     * 设置监听事件
     * @param paramonSizeChangedListenner
     */
    public void setOnSizeChangedListenner(InputMethodRelativeLayout.OnSizeChangedListenner paramonSizeChangedListenner) {
        this.onSizeChangedListenner = paramonSizeChangedListenner;
    }

    /**
     * 大小改变的内部接口
     * @author junjun
     *
     */
    public  interface OnSizeChangedListenner {
        void onSizeChange(boolean showKeyboard, int oldH, int newH);
    }
}

这样,使用该自定义layout的Activity只需要在回调onSizeChange中进行处理就可以了。

但是,当Activity设置为全屏时,即使activity属性设置为adjustResize,当键盘显示或隐藏时,这个方法也不会被触发,此时可以监听根View的变化。在Activity设置完layout后使用下面的一句话:

AndroidBug5497Workaround.assistActivity(this);
AndroidBug5497Workaround的代码如下:

package com.matrix.appsdk.widget.keyboard;

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

/**
 * @author BMR
 * @ClassName: AndroidBug5497Workaround
 * @Description: 解决Activity为全屏时设置为adjustResize,InputMethodRelativeLayout检测键盘不触发onSizeChanged
 * @date 2016/1/9 21:09
 */

//Workaround to get adjustResize functionality for input methos when the fullscreen mode is on
//found by Ricardo
//taken from http://stackoverflow.com/a/19494006
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 - r.top);
    }

}

这样,在利用开始的方法就可以了,onSizeChange就可以处理键盘事件了。

参考文档:

android 软键盘在全屏下的布局计算问题

android 软键盘的显示与隐藏问题的研究

				
时间: 2024-10-17 18:50:10

android监听键盘的相关文章

Android 监听ListView、GridView滑动到底部

// 监听listview滚到最底部mIndexList.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { // 当不滚动时 case OnScrollListener.SCROLL_STATE_IDLE: // 判断滚动到底部 if (view.get

Android监听ScrollView滑动到顶端和底部

MainActivity如下: package cn.testscrollview; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.ScrollView; import android.app.Activity; /** * Demo描述: * 监

Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.content.BroadcastReceiver;  import android.content.Context;  import android.content.Intent;  import android.net.ConnectivityManager;  import android.ne

android 监听网络状态的变化及实战

android 监听网络状态的变化及实际应用 转载请注明博客地址:http://blog.csdn.net/gdutxiaoxu/article/details/53008266 平时我们在请求错误的情况下,通常会进行处理一下,一般来说,主要分为两方面的错误 - 没有网络的错误 - 在有网络的情况下,我们客户端的错误或者服务器端的错误 今天这篇博客主要阐述以下问题 怎样监听网络状态的变化,包括是否打开WiFi,否打开数据网络,当前连接的网络是否可用 网络没有打开情况下的处理,如弹出对话框,跳转到

java 事件监听 - 键盘

//事件监听 //键盘事件监听,写了一个小案例,按上下左右,改变圆形的位置,圆形可以移动 import java.awt.*; import javax.swing.*; import java.awt.event.*; public class Index extends JFrame{ //设置面板 Wdmb wdmb = new Wdmb(); public static void main(String[] args) throws Exception{ //实例化当前类 Index i

Android监听HOME键的最简单的方法

public static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.getWindow().setFlags(FLAG_HOMEKEY_DISPATCHED, FLAG_HOMEKEY_DISPATCHED);//关键代码 setContentView(R.la

android 监听返回键

android监听返回键 public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { return true; } return super.onKeyDown(keyCode, event); } event.getRepeatCount() == 0重复次数:1次

Android 监听锁屏/开屏事件

1. 两种方案 (1) 监听BroadcastReceiver (2)获取PowerManager事件 2.  BroadcastReceiver 2.1. 事件 总共有3个事件: Intent.ACTION_SCREEN_ON : 屏幕点亮 Intent.ACTION_SCREEN_OFF :屏幕关闭 Intent.ACTION_USER_PRESENT: 用户解锁 2.2. 权限 监听用户解锁需要在AndroidManifest中注册权限 <uses-permission android:n

Android监听返回键、Home键+再按一次返回键退出应用

Android监听返回键需重写onKeyDown()方法 Home键keyCode==KeyEvent.KEYCODE_HOME [java] view plain copy @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { //++自定义点击事件 return tru