android实现底部弹出框与软键盘冲突(全面屏虚拟键适配)

    普通的底部弹出框大家都可以很熟练的使用了,无非是一个diaolog的事情,但是当dialog中含有输入框之后,软键盘与dialog的冲突可以说是十分坑了。。。更别说加上底部虚拟键了,这么一个小功能磨得我简直吐血。。。下面就是我的血泪史。 

第一阶段:    

  首先是底部dialog与软键盘的冲突:

       View myView = LayoutInflater.from(MainActivity.this).inflate(R.layout.pop,null);
        myView.setPadding(0, 0, 0, 0);
        Dialog dialog = new AlertDialog.Builder(MainActivity.this)
                .setView(myView).create();
        //设置点击Dialog外部任意区域关闭Dialog
        dialog.setCanceledOnTouchOutside(true);
        dialog.show();
        Window window = dialog.getWindow();            
        win.getDecorView().setPadding(0, 0, 0, ScreenUtils.getNavigationBarHeight(this));
        WindowManager.LayoutParams lp = win.getAttributes();
       lp.width = WindowManager.LayoutParams.MATCH_PARENT;
       lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
       lp.gravity = Gravity.BOTTOM;//设置对话框置底部显示

       win.setAttributes(lp);

      这时候dialog中的布局文件即R.layout.pop中含有edittext,每次我输入后想关闭软键盘,就顺手点击diaolog外部区域,这下好了。。。不仅软键盘关闭了,dialog也一起dimiss了。。。然后想着那就不让点击Dialog外部任意区域关闭Dialog生效呗,就把 dialog.setCanceledOnTouchOutside(true);这行代码注释掉,再运行,ok,我点即外部区域果然不会让dialog消失,但问题是软键盘也坚挺如初,毫不动摇,我手机自带的输入法当输入中文时候没有点击收起的小箭头。。。这下怎么搞。。。我想要点击外部diaolog不消失,只让软键盘消失啊!!!然后疯狂百度,得到解决方法如下:

      不使用dialog而是使用dialogActivity,嘿嘿,这样软键盘总不会和dialog纠缠不清,同上同下了吧。

   setContentView(R.layout.activity_main); 

       //设置窗口对齐屏幕宽度

    Window win = this.getWindow();
    win.getDecorView().setPadding(0, 0, 0, 0);
    WindowManager.LayoutParams lp = win.getAttributes();
    lp.width = WindowManager.LayoutParams.MATCH_PARENT;
    lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
    lp.gravity = Gravity.BOTTOM;//设置对话框置顶显示
    win.setAttributes(lp);
    //设置点击外部空白处可以关闭Activity,但我们不需要

    //this.setFinishOnTouchOutside(true); 

扫描二维码关注公众号,回复: 1373481 查看本文章

     当前activity要继承自AppCompatActivity,然后重写

@Override
public boolean onTouchEvent(MotionEvent event) {
    // TODO Auto-generated method stub
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        if(getCurrentFocus()!=null && getCurrentFocus().getWindowToken()!=null){
            InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }
    return super.onTouchEvent(event);
}
  这样,点击外部,就会让软键盘收起,且dialog不消失了(毕竟是activity了)

    当然,要在表单中注册这个activity

 <activity android:name=".MainActivity"      android:theme="@style/Base.V7.Theme.AppCompat.Light.Dialog"></activity>

   但是!!又双叒叕出问题了。。。activity撑不满屏宽啊,这肯定是样式问题了,我们看看这个dialog样式是怎样的吧

<style name="Base.V7.Theme.AppCompat.Light.Dialog" parent="Base.Theme.AppCompat.Light">
    <item name="android:colorBackground">?attr/colorBackgroundFloating</item>
    <item name="android:colorBackgroundCacheHint">@null</item>

    <item name="android:windowFrame">@null</item>
    <item name="android:windowTitleStyle">@style/RtlOverlay.DialogWindowTitle.AppCompat</item>
    <item name="android:windowTitleBackgroundStyle">@style/Base.DialogWindowTitleBackground.AppCompat</item>
    <item name="android:windowBackground">@drawable/abc_dialog_material_background</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowAnimationStyle">@style/Animation.AppCompat.Dialog</item>
    <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>

    <item name="windowActionBar">false</item>
    <item name="windowActionModeOverlay">true</item>

    <item name="listPreferredItemPaddingLeft">24dip</item>
    <item name="listPreferredItemPaddingRight">24dip</item>

    <item name="android:listDivider">@null</item>
</style>

这么多属性啊。。。好烦啊,一个个试,是哪个属性影响了全屏,结果发现了这个妖艳贱货

<item name="android:windowBackground">@drawable/abc_dialog_material_background</item>
<style name="noTitleDialogActivity" parent="Base.Theme.AppCompat.Light">
    <item name="android:colorBackground">?attr/colorBackgroundFloating</item>
    <item name="android:colorBackgroundCacheHint">@null</item>

    <item name="android:windowFrame">@null</item>
    <item name="android:windowTitleStyle">@style/RtlOverlay.DialogWindowTitle.AppCompat</item>
    <item name="android:windowTitleBackgroundStyle">@style/Base.DialogWindowTitleBackground.AppCompat</item>
    
<!--<item name="android:windowBackground">@drawable/abc_dialog_material_background</item>-->     //这个布局会让activity无法占满屏幕
<item name= "android:windowIsFloating" >true </item> <item name= "android:backgroundDimEnabled" >true </item> <item name= "android:windowContentOverlay" >@null </item> <item name= "android:windowAnimationStyle" >@style/Animation.AppCompat.Dialog </item> <item name= "android:windowSoftInputMode" >stateUnspecified|adjustPan </item> <item name= "windowActionBar" >false </item> <item name= "windowActionModeOverlay" >true </item> <item name= "listPreferredItemPaddingLeft" >24dip </item> <item name= "listPreferredItemPaddingRight" >24dip </item> <item name= "android:listDivider" >@null </item> </style>

theme中使用自己的样式,注释掉他!完美!全屏了!


第二阶段:

美滋滋的给测试测了,结果新问题穿线在全面屏手机虚拟键上,由于我的activity(包括dialogactivity都是使用沉浸样式)虚拟键区域在弹出框中会覆盖我的diaolog布局,而我的布局在地段有个提交按钮。。。你倒是给我浮起来一点啊!好吧,你赢了,我去获取你虚拟区域的高度可以吧,来给我的activity加个内增高,于是

Window win;//全局变量

win = this.getWindow();
win.getDecorView().setPadding(0, 0, 0, ScreenUtils.getNavigationBarHeight(this));
WindowManager.LayoutParams lp = win.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.BOTTOM;//设置对话框置底部显示
 win.setAttributes(lp);
 
 

但是,软键盘遮挡我的输入框又出现了,好吧,我监听你的软键盘弹出收起,然后一样给我的activity加个可活动的内增高,这下可行了吧,在activity中加个监听,另外新建一个帮助类

SoftKeyBoardListener.setListener(CheckDialogActivity.this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
    @Override
    public void keyBoardShow(int height) {
        win.getDecorView().setPadding(0, 0, 0, height);
        WindowManager.LayoutParams lp = win.getAttributes();
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.gravity = Gravity.BOTTOM;//设置对话框置底部显示
        win.setAttributes(lp);
    }

    @Override
    public void keyBoardHide(int height) {
        win.getDecorView().setPadding(0, 0, 0, ScreenUtils.getNavigationBarHeight(CheckDialogActivity.this));
        WindowManager.LayoutParams lp = win.getAttributes();
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.gravity = Gravity.BOTTOM;//设置对话框置底部显示
        win.setAttributes(lp);
    }
});

public class SoftKeyBoardListener {
    private View rootView;//activity的根视图
    int rootViewVisibleHeight;//纪录根视图的显示高度
    private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;

    public SoftKeyBoardListener(Activity activity) {
        //获取activity的根视图
        rootView = activity.getWindow().getDecorView();

        //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
        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);
    }
}

当你弹起多少,我就给activity上移多少,你收起,我就设置高度为虚拟栏高度,这下,总算搞定你这个磨人的小妖精了。。。  



第一次写这么多,大家点个赞可好!

猜你喜欢

转载自blog.csdn.net/qq_41642206/article/details/80536948