Android EditText被软键盘遮挡问题(问题记录)

Posted TheFlashArrow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android EditText被软键盘遮挡问题(问题记录)相关的知识,希望对你有一定的参考价值。

前言:这个问题在目前的开发生涯中,令我比较深刻,以至于过去快1年了,我还记忆犹新,在此记录一下。

场景:大约在1年前,当时负责的一个WMS仓储管理APP(Kotlin项目),线上突然反馈了“输入框被软键盘遮挡的问题”。接手问题后,使用线下物联网定制手持机调试复现中,系统版本为android 8.0。

问题现象:目前暂时没有设备,因而无法复现,故暂时不上gif图。这边口头描述一下:在页面中间部分有一个输入框,点击输入框唤出软键盘时,输入框被软键盘遮挡了一部分,这一部分就看不到了。遮挡程度取决于输入框位置,可能被遮挡部分或被全遮挡;位于页面上方的,比如搜索框之类的,不受影响;对于软件盘输入事件不影响,输入的数据还是能拿到的。 

解决:当时遇到这个问题,比较懵逼,且也找不到相关资料,只能不断试错,通过猜测进行尝试,中间也横向对比了其他项目,在该手持机上跑;转折点在“部分遮挡”情况下,部分遮挡的时候,输入的文字、光标都展示了一半,就感觉是可能是渲染问题,于是开启了项目全局硬件加速进行尝试,最终解决了问题。

<application>
    ...
    android:hardwareAccelerated="true"
</application>

 总结:一般没有冲突或其它连带问题情况下,硬件加速优先还是开启比较好。如果遇到项目不得不开启硬件加速,而其他地方开启硬件加速会出现问题的情况,则可以结合Application、Activity、Window、View这四个层面对硬件加速打开或关闭。

View开启硬件加速方法view.setLayerType(),源码如下:

/**
     * <p>Specifies the type of layer backing this view. The layer can be
     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
     * {@link #LAYER_TYPE_HARDWARE}.</p>
     *
     * <p>A layer is associated with an optional {@link android.graphics.Paint}
     * instance that controls how the layer is composed on screen. The following
     * properties of the paint are taken into account when composing the layer:</p>
     * <ul>
     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
     * </ul>
     *
     * <p>If this view has an alpha value set to < 1.0 by calling
     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
     * by this view's alpha value.</p>
     *
     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
     * for more information on when and how to use layers.</p>
     *
     * @param layerType The type of layer to use with this view, must be one of
     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
     *        {@link #LAYER_TYPE_HARDWARE}
     * @param paint The paint used to compose the layer. This argument is optional
     *        and can be null. It is ignored when the layer type is
     *        {@link #LAYER_TYPE_NONE}
     *
     * @see #getLayerType()
     * @see #LAYER_TYPE_NONE
     * @see #LAYER_TYPE_SOFTWARE
     * @see #LAYER_TYPE_HARDWARE
     * @see #setAlpha(float)
     *
     * @attr ref android.R.styleable#View_layerType
     */
    public void setLayerType(int layerType, @Nullable Paint paint) {
        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
        }

        boolean typeChanged = mRenderNode.setLayerType(layerType);

        if (!typeChanged) {
            setLayerPaint(paint);
            return;
        }

        if (layerType != LAYER_TYPE_SOFTWARE) {
            // Destroy any previous software drawing cache if present
            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
            // drawing cache created in View#draw when drawing to a SW canvas.
            destroyDrawingCache();
        }

        mLayerType = layerType;
        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
        mRenderNode.setLayerPaint(mLayerPaint);

        // draw() behaves differently if we are on a layer, so we need to
        // invalidate() here
        invalidateParentCaches();
        invalidate(true);
    }

Window开启硬件加速:

window.setFlags(
                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)

 参数解释如下:

/**
         * <p>Indicates whether this window should be hardware accelerated.
         * Requesting hardware acceleration does not guarantee it will happen.</p>
         *
         * <p>This flag can be controlled programmatically <em>only</em> to enable
         * hardware acceleration. To enable hardware acceleration for a given
         * window programmatically, do the following:</p>
         *
         * <pre>
         * Window w = activity.getWindow(); // in Activity's onCreate() for instance
         * w.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
         *         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
         * </pre>
         *
         * <p>It is important to remember that this flag <strong>must</strong>
         * be set before setting the content view of your activity or dialog.</p>
         *
         * <p>This flag cannot be used to disable hardware acceleration after it
         * was enabled in your manifest using
         * {@link android.R.attr#hardwareAccelerated}. If you need to selectively
         * and programmatically disable hardware acceleration (for automated testing
         * for instance), make sure it is turned off in your manifest and enable it
         * on your activity or dialog when you need it instead, using the method
         * described above.</p>
         *
         * <p>This flag is automatically set by the system if the
         * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
         * XML attribute is set to true on an activity or on the application.</p>
         */
        public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000;





以上是关于Android EditText被软键盘遮挡问题(问题记录)的主要内容,如果未能解决你的问题,请参考以下文章

安卓手机底部输入框被软键盘遮挡的坑

EditText底部边框被软键盘挡住的问题

android开发 软键盘出现后 防止EditText控件遮挡 总体平移UI

移动端 模拟键盘 盖住表单

为啥Android不会暂停视图完全被软键盘挡住的片段?

Android 底部按钮被软键盘顶起问题解决