Android软键盘遮住DialogFragment怎么解决

弹出一个底部DialogFragment,里面包含TextView,但是点击TextView后软键盘会遮挡内容。
想要的效果是软键盘弹出来时候,整个DialogFragment是顶在软键盘上方,如下图。

P.S:请直接粘代码,咋们不谈理论。

public class Popup extends DialogFragment {

...............

@Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        root = inflater.inflate(mItemId, null);

        final Dialog dialog = getDialog();

        Window window = dialog.getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();

        //取消标题
        window.requestFeature(Window.FEATURE_NO_TITLE);
        //去掉dialog默认的padding
        window.getDecorView().setPadding(0, 0, 0, 0);
        //取消设置弹窗自带的背景颜色
        window.setBackgroundDrawableResource(R.color.transparent);
        //设置导航栏颜
        window.setNavigationBarColor(Color.TRANSPARENT);
        //内容扩展到导航栏
        window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL);

        //设置是否可关闭
        dialog.setCancelable(mCancelable);
        //设置没有标题
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

        //设置Dialog的宽高
        lp.width = widthType;
        lp.height = heightType;
        //设置Dialog的位置在哪里
        lp.gravity = gravityType;

        ...................

        return root;
    }
}

img

img

img

该方案已经线上验证

将题主自定义布局替换为如下Dialog的布局. show()的时候延迟100毫秒显示。


package com.component.dialog;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.component.constant.DataContans;
import com.component.itface.OnItemClickRecyclerListener;
import com.component.util.CheckTextUtil;
import com.component.util.ScreenUtil;
import com.component.util.SoftKeyBoardListener;
import com.core.toaster.Toaster;
import com.ftoutiao.component.R;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class ChatEditDialog extends Dialog implements View.OnClickListener {

    private Context mContext;
    RelativeLayout ll_all;
    private Activity activity;
    private TextView send;
    private EditText et_content;
    private OnItemClickRecyclerListener onItemClickRecyclerListener;
    /**
     * 判断是否 需要 去除上次遗留的评论
     */
    private int chatId = 0;

    public ChatEditDialog(Context context, Activity mContext) {
        super(context);
        this.mContext = context;
        this.activity = mContext;
    }

    public void setOnItemClickRecyclerListener(OnItemClickRecyclerListener onItemClickRecyclerListener) {
        this.onItemClickRecyclerListener = onItemClickRecyclerListener;
    }

    public void setHintEditStr(String name) {
        if (TextUtils.isEmpty(name)) {
            et_content.setHint(activity.getResources().getString(R.string.send_comment_text));
            send.setText(activity.getResources().getString(R.string.send_text));
        } else {
            et_content.setHint(activity.getResources().getString(R.string.chat_hui) + name);
            send.setText(activity.getResources().getString(R.string.revert_txt));

        }
    }

    public void equelChatId(int id) {
        if (id == -1) {
            et_content.setText("");
        }
        if (chatId != id) {
            et_content.setText("");
        }
        chatId = id;
    }

    @Override
    public void show() {
        super.show();
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                et_content.requestFocus();
                et_content.requestFocusFromTouch();
                showKeyboard(et_content);
            }
        }, 100);
    }

    public ChatEditDialog(@NonNull Context context) {
        super(context);
        this.mContext = context;
    }


    Handler mHandler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
//        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().setDimAmount(0f);

        super.onCreate(savedInstanceState);
        setContentView(R.layout.commend_et_content);
        ll_all = findViewById(R.id.ll_all);
        et_content = findViewById(R.id.et_content);
        send = findViewById(R.id.send);
        send.setOnClickListener(this);
        initSizeView();
        addEditLister();
    }

    private void addEditLister() {
        send.setClickable(false);
        et_content.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {

                if (s.length() > 0) {
//                    send.setBackgroundResource(R.drawable.login_choose_login_shape);
                    send.setBackgroundResource(R.drawable.game_select_shape);
                    send.setTextColor(Color.parseColor("#FFFFFF"));
                    send.setClickable(true);
                    if (s.length() > 300) {
                        et_content.setText(s.subSequence(0, 300));
                        Toaster.show("最多输入300个字");
                    }
                } else {
//                  send.setBackgroundResource(com.ftoutiao.component.R.drawable.game_bottom_edit_shape);
                    send.setBackgroundResource(R.drawable.game_unselect_shape);
                    send.setTextColor(Color.parseColor("#FFFFFF"));
                    send.setClickable(false);
//                  send.setTextColor(Color.parseColor("#ACACAC"));
                }
            }
        });
        addKeyboardChangeListener();
    }

    /**
     * 显示键盘
     */
    public void showKeyboard(View view) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }

    /**
     * 显示键盘
     */
    public void hideKeyboard() {
        ScreenUtil.hideInput(activity);
    }

    private void addKeyboardChangeListener() {
        SoftKeyBoardListener.setListener(activity, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
            @Override
            public void keyBoardShow(int height) {
            }

            @Override
            public void keyBoardHide(int height) {
                dismiss();
            }
        });
    }

    @Override
    public void setOnDismissListener(@Nullable OnDismissListener listener) {
        super.setOnDismissListener(listener);
    }

    @Override
    public void dismiss() {
        ScreenUtil.hideInputMethod(getContext(), et_content);
        super.dismiss();
    }

    /**
     * 设置开始显示dialog的内容的位置
     */
    private void initSizeView() {
        Window window = this.getWindow();
        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//注意此处
        window.setGravity(Gravity.BOTTOM);
        window.getAttributes().windowAnimations = R.style.SlipDialogAnimation;
        window.setLayout(-1, -2);//这2行,和上面的一样,注意顺序就行;
    }

    @Override
    public void onClick(View view) {
        int i = view.getId();
        if (i == R.id.send) {
            if (onItemClickRecyclerListener != null) {
                if (CheckTextUtil.isFastDoubleClick()) return;

                if (CheckTextUtil.getIsTourish()) {
                    onItemClickRecyclerListener.onItemClick("hitesoft", 100);
                    return;
                }
                if (!DataContans.checkLogin()) {
                    onItemClickRecyclerListener.onItemClick("hitesoft", 13);
                    return;
                }
                String contentStr = et_content.getText().toString().trim();
                if (TextUtils.isEmpty(contentStr)) {
                    Toaster.show(activity.getResources().getString(R.string.input_comment_content_text));
                    return;
                }

                if (et_content.length() > 500) {
                    Toaster.show(activity.getResources().getString(R.string.limit_500_text));
                    return;
                }
                ScreenUtil.hideInputMethod(getContext(), et_content);
                et_content.setText("");
                onItemClickRecyclerListener.onItemClick(contentStr, 11);
            }
        }
    }
}

在你的代码里修改了一下,设置键盘windowSoftInputMode属性,详细介绍放在后面了,如果还是无效,可以在xml布局外层加一层ScrollView试一下。


public class Popup extends DialogFragment {
 
...............
 
@Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        root = inflater.inflate(mItemId, null);
 
        final Dialog dialog = getDialog();
 
        Window window = dialog.getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();
 
        //取消标题
        window.requestFeature(Window.FEATURE_NO_TITLE);
        //去掉dialog默认的padding
        window.getDecorView().setPadding(0, 0, 0, 0);
        //取消设置弹窗自带的背景颜色
        window.setBackgroundDrawableResource(R.color.transparent);
        //设置导航栏颜
        window.setNavigationBarColor(Color.TRANSPARENT);
        //内容扩展到导航栏
        window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL);
        // --------------------------此处设置windowSoftInputMode属性--------------
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        //-----------------------------------------------------------------------------------------
 
        //设置是否可关闭
        dialog.setCancelable(mCancelable);
        //设置没有标题
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
 
        //设置Dialog的宽高
        lp.width = widthType;
        lp.height = heightType;
        //设置Dialog的位置在哪里
        lp.gravity = gravityType;
 
        ...................
 
        return root;
    }
}

1、"stateUnspecified"软键盘的状态 (是否它是隐藏或可见 )没有被指定。系统将选择一个合适的状态或依赖于主题的设置。这个是为了软件盘行为默认的设置。
2、"stateUnchanged" 软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。
3、"stateHidden" 当用户选择该 Activity时,软键盘被隐藏——也就是,当用户确定导航到该 Activity时,而不是返回到它由于离开另一个 Activity。
4、"stateAlwaysHidden" 软键盘总是被隐藏的,当该 Activity主窗口获取焦点时。
5、"stateVisible" 软键盘是可见的,当那个是正常合适的时 (当用户导航到 Activity主窗口时 )。
6、"stateAlwaysVisible" 当用户选择这个 Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该 Activity时,而不是返回到它由于离开另一个 Activity。
7、"adjustUnspecified" 它不被指定是否该 Activity主 窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局 视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为 设置。
8、"adjustResize" 该 Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间
9、"adjustPan" 该 Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。

目前没有一个是能实现的

监听软键盘弹起,有高度回调,自己根据这个高度设置下间距就好了

/**
 * 软键盘显示隐藏的监听
 */
public class SoftKeyBoardListener {
    private View rootView;//activity的根视图
    private int rootViewVisibleHeight;//纪录根视图的显示高度
    private Rect rect;
    private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener;

    public SoftKeyBoardListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
        //获取activity的根视图
        rootView = activity.getWindow().getDecorView();
        //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
        globalLayoutListener = () -> {
            //获取当前根视图在屏幕上显示的大小
            rect = new Rect();
            rootView.getWindowVisibleDisplayFrame(rect);

            int visibleHeight = rect.height();
            System.out.println("" + visibleHeight);
            if (rootViewVisibleHeight == 0) {
                rootViewVisibleHeight = visibleHeight;
                int screenHeight = GenericTools.getScreenHeight(activity);
                if (rootViewVisibleHeight < screenHeight - 400)
                    if (onSoftKeyBoardChangeListener != null) {
                        onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
                    }
                return;
            }

            //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
            if (rootViewVisibleHeight == visibleHeight) {
                return;
            }

            //根视图显示高度变小超过200,可以看作软键盘显示了
            if (rootViewVisibleHeight - visibleHeight > 200) {
                if (onSoftKeyBoardChangeListener != null) {
                    onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
                }
                rootViewVisibleHeight = visibleHeight;
            } else if (visibleHeight - rootViewVisibleHeight > 200) {
                //根视图显示高度变大超过200,可以看作软键盘隐藏了
                if (onSoftKeyBoardChangeListener != null) {
                    onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
                }
                rootViewVisibleHeight = visibleHeight;
            }
        };
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
    }

    public interface OnSoftKeyBoardChangeListener {
        void keyBoardShow(int height);

        void keyBoardHide(int height);
    }

    public void unRegister() {
        if (globalLayoutListener != null) {
            rootView.getViewTreeObserver().removeOnGlobalLayoutListener(globalLayoutListener);
            rootView = null;
            globalLayoutListener = null;
        }
    }
}

img

window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

https://blog.csdn.net/weixin_39781930/article/details/117576233 瞅瞅这个,我之前收藏的一个键盘遮挡的文章