Android监听系统输入法键盘弹出显示与隐藏事件

Android监听系统输入法键盘弹出显示与隐藏事件

有时候需要监听Android系统输入法的弹出显示事件,比如:微信聊天时,不管你当前在聊天中的什么位置(上滑查看消息历史),每当你点击输入框时,都会自动帮你聚集到最新的聊天记录。
而android系统没有提供对应的API来监听输入法的显示与隐藏,那就需要我们自己来实现了。
我目前发现有2种方式可以实现。

实现原理:通过监听布局的高度变化来间接监听输入法的弹出事件


  • 方式一

通过父布局的onLayout回调高度的改变来判断输入法的显示与隐藏
上代码!

public class MyMeasureLinearLayout extends LinearLayout {
    public static final String TAG = "MeasureLinearLayout";
    public static final boolean DEBUG = true;

    private FragmentSizeObserver mObserver;

    private int initBottom = -1;
    private int initLeft  = -1;

    public MyMeasureLinearLayout(Context context){
        this(context, null);
    }

    public MyMeasureLinearLayout(Context context, AttributeSet attrs){
        this(context, attrs, 0);
    }

    public MyMeasureLinearLayout(Context context, AttributeSet attrs,
            int defStyleAttr){
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        super.onLayout(changed, l, t, r, b);
        Log.d(TAG, " changed  "+changed +" b "+b);
        if(initBottom == -1 || initLeft == -1){
            initBottom = b;
            initLeft   = l;
            return;
        }
        if(changed){
            Log.d(TAG, " height "+b +" width "+r
                    +" initBottom "+initBottom+" initLeft "+initLeft);
            int height = b - initBottom; //高度变化值(弹出输入法,布局变小,则为负值)
            int width  = r - initLeft;  // 当前屏幕宽度(对应输入法而言无影响)
            onInputSizeChanged(width, height);
        }   
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }
    private void onInputSizeChanged(int widthDiff,int heightDiff) {
        if(mObserver != null){
            mObserver.onFragmentSizeChanged(widthDiff, heightDiff);
        }
    }
    public void registFragmentSizeObserver(FragmentSizeObserver observer) {
        mObserver = observer;       
    }
    public interface FragmentSizeObserver{
        public void onFragmentSizeChanged(int wdiff,int hdiff);
    }
}

原理分析
自定义MyMeasureLinearLayout ,继承自LinearLayout,以该布局作为包含EditText View在内的父布局容器,当EditText获取焦点时,系统输入法弹出,则该父布局整体被上移了,下面留出空间来显示输入法,所以可以根据布局被移动前后的bottom值变化来计算出高度的差值

FragmentSizeObserver接口中的onFragmentSizeChanged方法表示高度发生变化时的回调,可以实现该方法来做输入法弹出与隐藏的逻辑。
代码参考:

实现
public void onFragmentSizeChanged(int wdiff, int hdiff) {
        if (DEBUG)
            Log.d(TAG, "onFragmentSizeChanged wdiff " + wdiff + " hdiff "
                    + hdiff);
//      doFragmentSizeChanged(wdiff, hdiff);
if(hdiff < -200){ // show soft input
// 处理输入法弹出事件
}
else if(hdiff == 0){ // hide soft input
// 处理输入法隐藏事件
            if(null != mMessageRoot){
                Log.d(TAG, "--keybord hide soft input--add messageRootListener ");
                //mMessageRoot.getViewTreeObserver().addOnGlobalLayoutListener(messageRootListener);
            }
        }
    }


  • 方式二

可以不用实现自定义的布局,只需要用系统原生的布局如LinearLayout或RelativeLayout,获取根布局的实例,设置监听OnGlobalLayoutListener,通过根布局高度变化大小来判断输入法的弹出。
原理和方式一类似。注意一定要是在根布局上监听。
代码参考

...
mMessageRoot = (RelativeLayout) root.findViewById(R.id.message_root);

if(null != mMessageRoot){
    mMessageRoot.getViewTreeObserver().addOnGlobalLayoutListener(messageRootListener);
        }

....
OnGlobalLayoutListener messageRootListener = new OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            int heightDiff = mMessageRoot.getRootView().getHeight() - mMessageRoot.getHeight();
            if(heightDiff > 250){  // 700c (113, 473); 880 (146, 728); 850 (219, 1044)
                // keybord has show
                if(null != mListView){
                    mListView.setSelectionFromTop(mDataList.size() - 1, -30);
                    mMessageRoot.getViewTreeObserver().removeOnGlobalLayoutListener(messageRootListener);// 执行完输入法弹出逻辑后,应及时取消监听
                    Log.d(TAG, "--keybord has show we set the select index :"+(mDataList.size() -1));
                }
            }
            Log.d(TAG, "--messageRootListener--heightDiff:"+heightDiff);
        }
    };
....

public void onFragmentSizeChanged(int wdiff, int hdiff) {
        if(hdiff == 0){ // hide soft input
            if(null != mMessageRoot){
                Log.d(TAG, "--keybord hide soft input--add messageRootListener ");
//输入法隐藏后,继续添加监听             
mMessageRoot.getViewTreeObserver().addOnGlobalLayoutListener(messageRootListener);
            }
        }
    }

总结:通过布局的高度变化来间接实现监听输入法的弹出事件,布局高度的变化监听有不同的方法,我列出的方法仅供参考,借此抛砖引玉,欢迎大家评论留言。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android手机的输入法弹出时,可能有以下几个原因: 1. 输入法未启用:首先要确保输入法已经启用。可以在手机设置中的“语言和输入法”或“键盘输入法”中查看所有安装的输入法,并选择需要使用的输入法。如果没有检测到要使用的输入法,可以尝试下载并安装相应的输入法应用程序。 2. 输入法未被选中:在应用程序中,点击文本输入框时,可能需要手动选择要使用的输入法。通过长按文本输入框,会弹出选项菜单,选择“输入法”并选择需要使用的输入法。 3. 输入法冲突:如果安装了多个输入法,可能会出现输入法冲突的情况,导致输入法无法弹出。可以尝试禁用除需要使用的输入法外的其他输入法,然后重新启动手机。 4. 软件冲突:某些应用程序可能与输入法软件存在冲突,导致无法弹出输入法。可以尝试卸载最近安装的应用程序,或在应用管理器中找到相关应用程序并清除其缓存数据。 5. 系统问题:偶尔,系统中的某些错误可能导致输入法无法弹出。可以尝试重启手机,以解决可能存在的临时问题。如果问题依然存在,可以考虑进行硬件重置或寻求专业技术支持。 总而言之,可以通过检查输入法的启用状态、选中输入法、解决输入法冲突、处理软件冲突、重启手机等方法来解决Android手机输入法弹出的问题。如果问题仍然无法解决,建议寻求专业技术支持。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值