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被软键盘遮挡问题(问题记录)的主要内容,如果未能解决你的问题,请参考以下文章