android 弹出软键盘覆盖了popupwindow的终极解决办法

本文详细介绍了在Android开发中如何解决PopupWindow被软键盘遮挡的问题,提供了两种有效的方法,一种适用于大部分设备,另一种能解决特定手机型号上的问题,确保用户输入体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在经过几年的经验累积之后,我终于决定整理一下曾经遇到的各种问题,给各位走在Android开发路上的朋友一点帮助,更多相关问题,请访问我的博客:http://blog.youkuaiyun.com/xiaoliluote 如果您对该问题有更多的解决方式,请留言,验证之后我会编辑博客

写之前,我想先吐槽一下,各大网站真的是垃圾水友多,一个人这么写,其它人就无脑抄,抄过去的好歹也自己试试效果啊,浪费大家的时间.

比如这样子的:

popupWindow.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

您老在复制这段代码发布到自己的博客之前,能不能去试试? popupWindow.setSoftInputMode(PopupWindow.INPUT_METHOD_NEEDED); 这行代码虽然不会导致编译失败,但是它下面画着红色波浪线的,您眼瞎看不到吗? 正确的写法是setInputMethodMode,而不是setSoftInputMode.

笔者遇到的场景是:在Activity中点击购买,会从底部弹出PopupWindow,然后在该PopupWindow中有个EditText允许用户自行输入购买数量,此时弹出的软键盘,会覆盖掉popupWindow的内容,体验效果就很糟糕了.

在注册文件中设置android:windowSoftInputMode="adjustResize" 是没有用的,它只有在Activity的EditText里面才有用,这里是在PopupWindow里面.

好,吐槽完毕,下面说方案

1.上面的方案,放在popupWindow的show方法之前,在部分手机是有效的,也就是这样子用:

View view = LayoutInflater.from(this).inflate(R.layout.view_pop, null);  
        popview = new PopupWindow(view,  
                android.view.ViewGroup.LayoutParams.MATCH_PARENT,  
                LayoutParams.WRAP_CONTENT, true);  
        popview.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));  
        popview.setFocusable(true);  
        // 设置点击其他地方就消失  
        popview.setOutsideTouchable(true);  
        popview.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);  
        popview.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);  
        popview.showAtLocation(ll_all, Gravity.BOTTOM  
                | Gravity.CENTER_VERTICAL, 0, 0); 

2.笔者在亲测中发现,手里的一款乐视手机没得用,软件盘还是覆盖了PopupWindow的内容,如果您在测试中也遇到了该问题,那么用下面这个方案吧,应该是可以解决所有手机的问题.

这里借鉴了该网友的部分代码,附上链接,尊重别人的劳动成果:https://www.jianshu.com/p/9bba256f261f

但该网友的办法,在使用时,发现第一次弹出软键盘无效,原因是第一次弹出软键盘的时候,没有测量视图的高度,所以没有进入到软键盘弹出的监听方法,这里贴出修改过后的完整源代码:

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

/**
 * Created by KillaXiao on 2019/8/14.
 * 监听软键盘的弹出与收起, 在部分手机测试到,popupwindow里面有edittext的时候,弹出软键盘,会覆盖掉从底部弹出的popupwindow内容
 */
public class SoftKeyBoardListener {
    private View rootView;  //activity的根视图
    int rootViewVisibleHeight;  //纪录根视图的显示高度
    private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
    public SoftKeyBoardListener(Activity activity) {
        //获取activity的根视图
        rootView = activity.getWindow().getDecorView();
        Rect r = new Rect();
        rootView.getWindowVisibleDisplayFrame(r);
        int visibleHeight = r.height();
        rootViewVisibleHeight = visibleHeight;

        //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //获取当前根视图在屏幕上显示的大小
                Rect r = new Rect();
                rootView.getWindowVisibleDisplayFrame(r);
                int visibleHeight = r.height();
                System.out.println(""+visibleHeight);
                if (rootViewVisibleHeight == 0) {
                    rootViewVisibleHeight = visibleHeight;
                    return;
                }
                //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
                if (rootViewVisibleHeight == visibleHeight) {
                    return;
                }
                //根视图显示高度变小超过200,可以看作软键盘显示了
                if (rootViewVisibleHeight - visibleHeight > 200) {
                    if (onSoftKeyBoardChangeListener != null) {
                        onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
                    }
                    rootViewVisibleHeight = visibleHeight;
                    return;
                }
                //根视图显示高度变大超过200,可以看作软键盘隐藏了
                if (visibleHeight - rootViewVisibleHeight > 200) {
                    if (onSoftKeyBoardChangeListener != null) {
                        onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
                    }
                    rootViewVisibleHeight = visibleHeight;
                    return;
                }
            }
        });
    }
    private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
        this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
    }
    public interface OnSoftKeyBoardChangeListener {
        void keyBoardShow(int height);
        void keyBoardHide(int height);
    }
    public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
        SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
        softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
    }
}

然后在PopupWindow中设置监听:

LinearLayout content_container;
//该方法先执行,测量一下布局的高度,笔者是自己写了一个class继承PopupWindow,固这里都是私有方法
private void initView(){
content_container = view.findViewById(R.id.content_container);
int width = View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED);
        int temp_height = View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED);
        content_container.measure(width, temp_height);
}

//布局高度测量完毕之后,设置监听
private void softInputListener(Activity mContext){
        SoftKeyBoardListener.setListener(mContext, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
            @Override
            public void keyBoardShow(int height) {
                ViewGroup.LayoutParams layoutParams = content_container.getLayoutParams();
            //用父布局的原高度 + 软键盘弹出的高度 设置为父布局的新高度,软键盘就实际是覆盖了空白的部分,就不会遮挡住原popupWindow的内容了
                layoutParams.height = content_container.getMeasuredHeight()+height;
                content_container.setLayoutParams(layoutParams);
                content_container.invalidate();
            }

            @Override
            public void keyBoardHide(int height) {
            //关闭软键盘时,再把布局高度设置回来
                ViewGroup.LayoutParams layoutParams = content_container.getLayoutParams();
                layoutParams.height = content_container.getMeasuredHeight()-height;
                content_container.setLayoutParams(layoutParams);
                content_container.invalidate();
            }
        });
    }

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值