聊天界面软键盘和其他布局完美切换

本文介绍了一种解决聊天应用中软键盘与表情、图片及语音布局切换时出现跳动问题的方法。通过保存软键盘高度并在不同布局间平滑切换,确保用户体验。提供了具体的实现代码。

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

        


       在搭建聊天页面的时候,软键盘和表情布局,选图片布局以及语音布局切换的时,会出现布局跳动的现象,这里github上找了一个大牛写的自定义控件,完美解决了这个问题,我把Studio上的项目转移到的IDEA上,并写成了依赖包。

      首先,为了在聊天页面第一次弹出表情或者其他布局时,高度是和软件盘的高度一致,需要在聊天页面之前,有软键盘弹出的地方,保存一下软键盘的高度,一般选在登录或者注册页面,添加一个方法即可。。。。

<span style="font-size:18px;">/**
     * 获取软键盘的高度并保存
     */
    private void saveKeyBoardHeight(){
        final View decorView = getWindow().getDecorView();
        decorView.getViewTreeObserver().
                addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    /**
                     * the result is pixels
                     */
                    @Override
                    public void onGlobalLayout() {
                        Rect r = new Rect();
                        decorView.getWindowVisibleDisplayFrame(r);
                        int screenHeight = decorView.getRootView().getHeight();
                        int heightDifference = screenHeight - (r.bottom - r.top);
                        Log.e("KeyboardSize", "KeyboardSize:  " + heightDifference);
                        if (heightDifference > 200){
                            KeyboardUtil.saveKeyboardHeight(MyActivity.this, heightDifference - r.top);
                        }
                    }
                });
    }</span>


其次,在聊天的页面加入两段代码:

<span style="font-size:18px;">/**
         * 这个方法是布局和软键盘平缓切换的关键
         */
        KeyboardUtil.attach(this, mPanelRoot,
                // Add keyboard showing state callback, do like this when you want to listen in the
                // keyboard's show/hide change.
                new KeyboardUtil.OnKeyboardShowingListener() {
                    @Override
                    public void onKeyboardShowing(boolean isShowing) {
                        Log.d(TAG, String.format("Keyboard is %s", isShowing ? "showing" : "hiding"));
                    }
                });

        KPSwitchConflictUtil.attach(mPanelRoot, mPlusIv,mVoiceIv,null,mSendEdt,
                new KPSwitchConflictUtil.SwitchClickListener() {
                    @Override
                    public void onClickSwitch(boolean switchToPanel, int flag) {

                        if (switchToPanel) {
                            mSendEdt.clearFocus();
                            // flag 标志位
                            // 显示那个布局自己定
                            if (flag == 1){
                                layout1.setVisibility(View.VISIBLE);
                                layout2.setVisibility(View.GONE);
                            }else{
                                layout1.setVisibility(View.GONE);
                                layout2.setVisibility(View.VISIBLE);
                            }
                        } else {
                            mSendEdt.requestFocus();
                            Log.d("switchToPanel"," false ==  "+flag);
                        }
                    }
                });</span>


页面切换的逻辑关键代码在 KPSwitchConflictUtil的attach方法中:

public static void attach(/** 根布局  **/final View panelLayout,
                              /** 点击btn  **/final View switchBtnOne,
                              /** 点击btn  **/final View switchBtnTwo,
                              /** 点击btn  **/final View switchBtnThree,
                              /** Edittext  **/final View focusView,
                              /** Nullable **/final SwitchClickListener switchClickListener) {
        final Activity activity = (Activity) panelLayout.getContext();

        if (switchBtnOne != null) {
            switchBtnOne.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int flag = 1;
                    // 如果显示的是软键盘
                    if (mFlag == 0){
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(true,flag);
                        }
                        showPanel(panelLayout);
                        mFlag = flag;

                    }else if (mFlag == flag){
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(false,flag);
                        }
                        showKeyboard(panelLayout, focusView);
                    }else{
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(true,flag);
                        }
                        showPanel(panelLayout);
                        mFlag = flag;
                    }
                }
            });
        }

        if (switchBtnTwo != null) {
            switchBtnTwo.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d("mFlag", " switchBtnTwo  mFlag ==  " + mFlag);
                    int flag = 2;
                    if (mFlag == 0){
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(true,flag);
                        }
                        showPanel(panelLayout);
                        mFlag = flag;

                    }else if (mFlag == flag){
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(false,flag);
                        }
                        showKeyboard(panelLayout, focusView);
                    }else{
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(true,flag);
                        }
                        showPanel(panelLayout);
                        mFlag = flag;
                    }


                }
            });
        }

        if (switchBtnThree != null) {
            switchBtnThree.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int flag = 3;
                    if (mFlag == 0){
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(true,flag);
                        }
                        showPanel(panelLayout);
                        mFlag = flag;

                    }else if (mFlag == flag){
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(false,flag);
                        }
                        showKeyboard(panelLayout, focusView);
                    }else{
                        if (switchClickListener != null) {
                            switchClickListener.onClickSwitch(true,flag);
                        }
                        showPanel(panelLayout);
                        mFlag = flag;
                    }
                }
            });
        }


        if (isHandleByPlaceholder(activity)) {
            focusView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        /**
                         * Show the fake empty keyboard-same-height panel to fix the conflict when
                         * keyboard going to show.
                         * @see KPSwitchConflictUtil#showKeyboard(View, View)
                         */
                        panelLayout.setVisibility(View.INVISIBLE);
                    }
                    return false;
                }
            });
        }
    }

原本的逻辑被我修改一下,因为他只有一个布局,考虑到我们的项目需要表情、图片、语音三部分,所以修改成三个布局和软键盘切换。如果需要更多可在这里继续添加,如果不需要三个,传入null即可。


还有,给EditText设置点击或者触摸事件,点击的时候把显示布局的标志位置为0.

<span style="font-size:18px;">mSendEdt.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    KPSwitchConflictUtil.mFlag = 0;
                }
                return false;
            }
        });</span>

源码地址:http://download.youkuaiyun.com/detail/qq55214/9566481


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值