美文网首页自定义ViewAndroid知识Android开发
对网上【自定义输入框】的改动

对网上【自定义输入框】的改动

作者: zzEND | 来源:发表于2017-03-17 17:10 被阅读114次

    开发APP的时候经常会遇到的一个需求就是“自定义一个输入框”,市面上几乎所有app的输入框基本都是他们自己开发的。

    自定义布局并非难事,难的是当软键盘弹出时,如何保证你的输入框能自动被顶起。

    作为一个新手,遇到问题先百度一下,果然很快就在网上找到了“解决方案”:

     View decorView = getWindow().getDecorView();
     View contentView = mEditText;// 此处的控件ID可以使用界面当中的指定的任意控件
     decorView.getViewTreeObserver().addOnGlobalLayoutListener(getGlobalLayoutListener(decorView, contentView));
    
    
    private ViewTreeObserver.OnGlobalLayoutListener getGlobalLayoutListener(final View decorView, final View contentView) {
        return new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                decorView.getWindowVisibleDisplayFrame(r);
    
                int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                int diff = height - r.bottom;
    
                if (diff != 0) {
                    if (contentView.getPaddingBottom() != diff) {
                        contentView.setPadding(0, 0, 0, diff);
                    }
                } else {
                    if (contentView.getPaddingBottom() != 0) {
                        contentView.setPadding(0, 0, 0, 0);
                    }
                }
            }
        };
    }
    

    这段代码你能很轻易的在网上找到,作用大概是:声明getGlobalLayoutListener()方法,传入你的手机屏幕与指定的控件。ViewTreeObserver会监听你的屏幕,当软键盘弹出时,屏幕可见高度(r.bottom)变小。计算屏幕高度与r.bottom的差值,即为软键盘的高度(diff)。将指定控件的paddingBottom设为diff,就实现了“自定义输入框位于软键盘上方”。同理,当软键盘消失时,paddingBottom设为0,输入框自动落回底部。

    这段代码本身没有问题,在绝大多数情况下都可以正常使用。可是根据我的测试,在部分Android4.4的手机上,会出现bug,具体表现为“输入框移动的高度变为软键盘高度的两倍”。

    具体原因不明,我初步怀疑是setPadding的的处理机制不同导致的bug。如果padding是从屏幕底部开始计算,则padding值等于软键盘高度是没问题的。可是如果padding是从屏幕可见区域开始计算的,那么此时不需要paddingBottom。

    于是我改了一下控件位移的方式,不再使用setPadding。下面是我改动后的代码:

    private ViewTreeObserver.OnGlobalLayoutListener getGlobalLayoutListener(final View decorView, final View contentView){
            return new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    Rect r = new Rect();
                    decorView.getWindowVisibleDisplayFrame(r);
    
                    int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                    int diff = decorView.getHeight() - r.bottom;
    
                    if (diff != 0) {
                        if (contentView.getPaddingBottom() != diff) {
                            contentView.setY(r.bottom - contentView.getHeight());
                        }
                    } else {
                        contentView.setY(decorView.getHeight() - contentView.getHeight());
                    }
                }
            };
        }
    

    我这里仅仅是将setPadding改为了setY,直接指定空间的坐标高度,这样适配问题就解决了。注意Y值等于屏幕可见高度(r.bottom)减去控件高度( contentView.getHeight() )

    相关文章

      网友评论

        本文标题:对网上【自定义输入框】的改动

        本文链接:https://www.haomeiwen.com/subject/eigenttx.html