时间:2021-05-20
当一个activity中含有输入框时,我们点击输入框,会弹出输入法界面,整个界面的变化效果与manifest中对应设置的android:windowSoftInputMode属性有关,一般可以设置的值如下,
<activity android:windowSoftInputMode=["stateUnspecified","stateUnchanged”, "stateHidden","stateAlwaysHidden”, "stateVisible","stateAlwaysVisible”, "adjustUnspecified","adjustResize”, "adjustPan"] …… >具体怎么设置可以查看官方文档。今天主要解决当输入法弹出时会覆盖输入框的问题。
什么情况会覆盖?
当android的应用中如果一个activity设置了全屏属性Theme.Light.NotittleBar.Fullscreen或者设置了activity对应的主题中android:windowTranslucentStatus属性,设置方式为:<item name="android:windowTranslucentStatus">true</item>,这是如果对应的页面上含有输入框,将会导致点击输入框时软键盘弹出后键盘覆盖输入框,导致输入框看不见。
为什么?
这其实是因为在全屏时,adjustResize属性已经失效了,该问题是系统的一个bug,参考链接。adjustResize不生效,那有没有其他方法来解决呐? 这时我们可以设置adjust属性为adjustPan属性,该属性不会失效,但是由于adjustPan会将页面整体平移,以留出输入法空间,会有一个抖动的效果,体验很差,哪有没有体验效果更好的方法呐?
解决方案:
如果跟布局采用FrameLayout,则可以复写一个自定义FrameLayout,同时设置FrameLayout的android:fitsSystemWindows属性为true。xml设置如下
<com.sample.ui.widget.InsetFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true”>我们自定义该FrameLayout为InsetFrameLayout,InsetFrameLayout 代码如下:
public final class InsetFrameLayout extends FrameLayout { private int[] mInsets = new int[4]; public InsetFrameLayout(Context context) { super(context); } public InsetFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } public InsetFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public final int[] getInsets() { return mInsets; } @Override protected final boolean fitSystemWindows(Rect insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Intentionally do not modify the bottom inset. For some reason, // if the bottom inset is modified, window resizing stops working. mInsets[0] = insets.left; mInsets[1] = insets.top; mInsets[2] = insets.right; insets.left = 0; insets.top = 0; insets.right = 0; } return super.fitSystemWindows(insets); } @Override public final WindowInsets onApplyWindowInsets(WindowInsets insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { mInsets[0] = insets.getSystemWindowInsetLeft(); mInsets[1] = insets.getSystemWindowInsetTop(); mInsets[2] = insets.getSystemWindowInsetRight(); return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0, insets.getSystemWindowInsetBottom())); } else { return insets; } }}官方解决方案:
官方其实也发现了问题,因此在android.support.design.internal下也重写了FrameLayout来解决该问题,但是该类被标记了hide。
/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://pat.postInvalidateOnAnimation(ScrimInsetsFrameLayout.this); return insets.consumeSystemWindowInsets(); } }); } @Override public void draw(@NonNull Canvas canvas) { super.draw(canvas); int width = getWidth(); int height = getHeight(); if (mInsets != null && mInsetForeground != null) { int sc = canvas.save(); canvas.translate(getScrollX(), getScrollY()); // Top mTempRect.set(0, 0, width, mInsets.top); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Bottom mTempRect.set(0, height - mInsets.bottom, width, height); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Left mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); // Right mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom); mInsetForeground.setBounds(mTempRect); mInsetForeground.draw(canvas); canvas.restoreToCount(sc); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mInsetForeground != null) { mInsetForeground.setCallback(this); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mInsetForeground != null) { mInsetForeground.setCallback(null); } }}采用如上其中的任何一种方法就可以解决输入法弹出后覆盖输入框问题。
其他问题?
在我们使用的过程中发现有用户反馈,说只要进入我们采用该布局的页面就会崩溃,我们查看了崩溃日志,发现有部分手机都使用了相同的一个安卓系统,并且版本都是19,android4.4.x,一个被重写过的系统,该系统的代码加载方式被重写了。
为什么会崩溃?
我们代码使用到了WindowInsets,该类是api 20才提供的,因此19的系统中其实是没有该代码的,但是该系统在xml的inflate的时候就解析了该类,导致classNotFound。
新的解决方案!
新的解决方案还是采用了上述的方式,不过会针对不同的版本写不一样的布局,分别为api 20以上与20以下提供不同的布局,这是采用系统的限定符实现的,之后20以上的原样采用上述的方式,20以下去掉onApplyWindowInsets复写,这样不同的版本加载不同的代码就OK了。
@Override public final WindowInsets onApplyWindowInsets(WindowInsets insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { mInsets[0] = insets.getSystemWindowInsetLeft(); mInsets[1] = insets.getSystemWindowInsetTop(); mInsets[2] = insets.getSystemWindowInsetRight(); return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0, insets.getSystemWindowInsetBottom())); } else { return insets; } }总结到此整个解决方案已经完成了,如过有更新的解决方案望大家分享。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
1、可能是您游戏时的输入法被切换成了中文输入法,在使用键盘操作时会自动弹出输入框,也会将游戏弹出回到桌面,使用【Shift】切换为英文输入就可以解决; 2
qq输入法删除记忆的方法如下: 1、首先找到任意一个输入框的地方,如百度搜索框; 2、在输入框处,将输入法切换到“QQ输入法”; 3、用“QQ输入法”打出
电脑输入法切换不了的原因及解决方法电脑输入法切换不了的原因及解决方法电脑输入法切换不了的原因及解决方法电脑输入法切换不了的原因及解决方法电脑输入法切换不了的原因
之前要做一个弹出对话框,填写信息,发现在手机上看的时候,较后的输入框在填写信息时,输入框被输入法遮挡,只能盲填。前提1.弹出的对话框用display:fixed
搜狗拼音输入法2012https:///softs/6105.html下面就来分享下搜狗输入法怎样更换皮肤调出输入法输入框右键单击输入框,选择“设置