欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 软键盘遮挡问题解决

程序员文章站 2022-04-19 23:13:28
...

常规解决方式

setContentView();之前加入getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

非常规情况

上述方式设置失效时(在设置页面全屏,状态栏透明后设置会不起作用,项目中遇到过头疼了好久)
解决原理:
1.使用ViewTreeObserver.OnGlobalLayoutListener 注册监听视图树的观察者,监听可视区的高度变化来获取键盘高度

public class KeyBoardHeightUtil  implements ViewTreeObserver.OnGlobalLayoutListener {

    private final static String TAG = "KeyBoardHeightUtil";
    private View mParentView;
    private Rect mRect;
    private int mScreenHeight;
    private int mScreenStatusHeight;
    private int mLastRectHeight;
    private KeyBoardHeightChangeListener mKeyBoardChangeListener;
    private boolean mSoftInputShowed;
    private int mErrorHeight;
    private boolean mFirst = true;
    private int mLastKeyBoardHeight;

    public KeyBoardHeightUtil(Context context, View parentView, KeyBoardHeightChangeListener listener) {
        mParentView = parentView;
        mRect = new Rect();
        mFirst = true;
        ScreenDimenUtil util = ScreenDimenUtil.getInstance();
        mScreenHeight = util.getScreenHeight();
        mScreenStatusHeight = util.getStatusBarHeight();
        L.e(TAG, "---屏幕高度--->" + mScreenHeight);
        L.e(TAG, "---状态栏高度--->" + mScreenStatusHeight);
        mKeyBoardChangeListener = new WeakReference<>(listener).get();
    }


    @Override
    public void onGlobalLayout() {
        L.e(TAG, "-------onGlobalLayout--->");
        if (mParentView != null && mRect != null) {
            mParentView.getWindowVisibleDisplayFrame(mRect);
            int curRectHeight = mRect.height();
            if (mFirst) {
                mFirst = false;
                mScreenHeight = curRectHeight + mScreenStatusHeight;
                mLastRectHeight = curRectHeight;
            }
            if (mLastRectHeight != curRectHeight) {
                mLastRectHeight = curRectHeight;
                int visibleHeight = curRectHeight + mScreenStatusHeight;
                int keyboardHeight = mScreenHeight - visibleHeight;
                mSoftInputShowed = keyboardHeight > mScreenHeight / 4;
                if (mSoftInputShowed) {
                    keyboardHeight -= mErrorHeight;
                } else {
                    if (keyboardHeight > 0) {
                        mErrorHeight = keyboardHeight;
                    }else {
                        mErrorHeight = 0;
                    }
                    keyboardHeight = 0;
                }
                visibleHeight = mScreenHeight - keyboardHeight;
                if (mLastKeyBoardHeight != keyboardHeight) {
                    mLastKeyBoardHeight = keyboardHeight;
                    L.e(TAG, "-------可视区高度----->" + visibleHeight);
                    L.e(TAG, "-------键盘高度----->" + keyboardHeight);
                    if (mKeyBoardChangeListener != null) {
                        mKeyBoardChangeListener.onKeyBoardHeightChanged(visibleHeight, keyboardHeight);
                    }
                }
            }
        }
    }


    /**
     * 添加布局变化的监听器
     */
    public void start() {
        if (mParentView != null) {
            mParentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
            L.e(TAG, "-------添加键盘监听--->");
            Log.e("wzl", "-------添加键盘监听--->");
        }
    }


    /**
     * 移除布局变化的监听器
     */
    public void release() {
        if (mParentView != null) {
            mParentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
        mParentView = null;
        mRect = null;
        mKeyBoardChangeListener = null;
        L.e(TAG, "-------移除键盘监听--->");
    }


    public boolean isSoftInputShowed() {
        return mSoftInputShowed;
    }
}

2.根据键盘高度重新设置根布局的底部边距

    private void onKeyBoardChanged(int keyboardHeight) {

        if (mRootView != null) {
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mRootView.getLayoutParams();
            if (params.bottomMargin != keyboardHeight) {
                params.bottomMargin = keyboardHeight;
                mRootView.setLayoutParams(params);
                scrollToBottom();//移动被软键盘遮挡的view
            }
        }
    }

3.移动被软键盘遮挡的view
我这里移动的是recycleview

mLayoutManager.scrollToPositionWithOffset(mList.size() - 1, -DpUtil.dp2px(20));

KeyBoardHeightUtil 初始化方法

mKeyBoardHeightUtil = new KeyBoardHeightUtil(this, findViewById(android.R.id.content), this);
mRootView.post(new Runnable() {
            @Override
            public void run() {
                if (mKeyBoardHeightUtil != null) {
                    mKeyBoardHeightUtil.start();
                }
            }
        });

接口实现

    @Override
    public void onKeyBoardHeightChanged(int visibleHeight, int keyboardHeight) {
        if (mPaused) {
            return;
        }
        //监听到键盘高度后,改变底部边距
        onKeyBoardChanged(keyboardHeight);
    }

    @Override
    public boolean isSoftInputShowed() {
        if (mKeyBoardHeightUtil != null) {
            return mKeyBoardHeightUtil.isSoftInputShowed();
        }
        return false;
    }