很久没写博客,最近项目遇到需要获取输入法高度将EditText上移的效果,实现方式本来有几种

1.设置softInputMode WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
但是这样布局中如果有RecyclerView,或者ScrollView的时候,整个布局会向上滚动,但是我不想让他滚动,
执行编辑框上移

2.网上有一个SoftSoftInputKeyBoardUtil类,原理是通过获取可见高度来计算键盘高度,但是测试发现有些手机获取到的高度是不正确的,
有的高一些,有的低一些,(普遍是状态栏和导航栏的高度影响),特别是一些手机有导航栏一键隐藏功能,可以随时显示或隐藏导航栏,
设置隐藏时候,如果弹出输入法,又会自动加上导航栏,导致高度计算错误

下面介绍一种新的实现方式,从fitSystemWindow的灵感发现。( softInputMode需要是adjustResize
设置fitSystemWindow后,会发现我们即使不用上面的监听方法,编辑框也能自己被输入法推上去,但是缺点是View会被添加一段白色的长条,这是由于适应适应系统窗口,系统会为我们给布局view加上pading,留出系统窗口占据的大小,但是有一些浸入式的实现方式可能会被破坏,需要我们手动修改状态栏颜色,从而有可能影响到其他页面的状态栏颜色(如果未及时重置颜色)

1.相关类

从源码中发现这样一个方法,在View和ViewCompat类中

View.java

* Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying * window insets to this view. The listener's * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} * method will be called instead of the view's * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. * @param listener Listener to set * @see #onApplyWindowInsets(WindowInsets) public void setOnApplyWindowInsetsListener ( OnApplyWindowInsetsListener listener ) { getListenerInfo ( ) . mOnApplyWindowInsetsListener = listener ;

ViewCompat.java

* Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying * window insets to this view. This will only take effect on devices with API 21 or above. public static void setOnApplyWindowInsetsListener ( @NonNull View v , final OnApplyWindowInsetsListener listener ) { if ( Build . VERSION . SDK_INT >= 21 ) { if ( listener == null ) { v . setOnApplyWindowInsetsListener ( null ) ; return ; v . setOnApplyWindowInsetsListener ( new View . OnApplyWindowInsetsListener ( ) { @Override public WindowInsets onApplyWindowInsets ( View view , WindowInsets insets ) { WindowInsetsCompat compatInsets = WindowInsetsCompat . wrap ( insets ) ; compatInsets = listener . onApplyWindowInsets ( view , compatInsets ) ; return ( WindowInsets ) WindowInsetsCompat . unwrap ( compatInsets ) ; } ) ;

两者没有太大差别,ViewCompat帮我们对View中的一些方法做了版本兼容

api介绍是这个listener会去接管view中对于 窗口嵌入物 的处理,

2.窗口嵌入物都指什么

嵌入物的数据通过 WindowInsets 表示

稍微看下WindowInsets

重点看下 mSystemWindowInsets

public final class WindowInsets {
     * Returns the left system window inset in pixels.
     * <p>The system window inset represents the area of a full-screen window that is
     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
     * @return The left system window inset
	 * 这个表示全屏模式下,部分或者全部被状态栏,导航栏,输入法或其他系统窗口遮挡的那部分区域
	 * 这些代码是我从这个类下两个地方拼接的,方便说明这个变量
	private Rect mSystemWindowInsets;
    private Rect mWindowDecorInsets;
    private Rect mStableInsets;
    private Rect mTempRect;
    private boolean mIsRound;
    private DisplayCutout mDisplayCutout;

systemWindowInset就是我们要用的东西

* Returns the left system window inset in pixels. * @return The left system window inset public int getSystemWindowInsetLeft() { return mSystemWindowInsets.left; * Returns the top system window inset in pixels. * @return The top system window inset public int getSystemWindowInsetTop() { return mSystemWindowInsets.top; * Returns the right system window inset in pixels. * @return The right system window inset public int getSystemWindowInsetRight() { return mSystemWindowInsets.right; * Returns the bottom system window inset in pixels. * @return The bottom system window inset public int getSystemWindowInsetBottom() { return mSystemWindowInsets.bottom;

这几个方法,分别获取左,上,右,下位置的遮挡

在这里插入图片描述
这2个值就是从手机边缘算起,嵌入物遮挡的距离

结论:我们可以给View设置这个Listener,获取WindowInsets,获取 getSystemWindowInsetBottom 得到底部被系统窗口嵌入物遮挡的距离,这样就由系统去计算移动的距离(不管你是导航栏还是输入法还是其他的,或者一起出现,遮挡窗口),然后将需要上移的view移动这个距离,通过设置padding或者marin即可。

ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
            setPadding(0, 0, 0, insets.systemWindowInsetBottom)
            insets

这样就可以实现输入法弹起,编辑框上移,关闭输入法,编辑框复原位置

ViewCompat.setOnApplyWindowInsetsListener() 兼容到api 21 也就是5.0

View.setOnApplyWindowInsetsListener() 要求最低版本 20

更低版本可以通过覆写View onApplyWindowInsets来获取WindowInsets

再次提醒: windowSoftInputMode 设置未adjustResize

如果有错误,欢迎讨论,如果能解决你的问题,那就太高兴了

欢迎留言,让我知道这篇文章是否对大家有帮助

很久没写博客,最近项目遇到需要获取输入法高度将EditText上移的效果,实现方式本来有几种1.设置softInputMode WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN但是这样布局中如果有RecyclerView,或者ScrollView的时候,整个布局会向上滚动,但是我不想让他滚动,执行编辑框上移2.往上有一个SoftSoftInputKeyBoardUtil类,原理是通过获取可见高度来计算键盘高度,但是测试发现有些手机获取到的高度是不正确的 我们都知道在 Android 上软键盘弹出会使我们的窗口高度被压缩,这时我们可能就要通知界面做出调整以适应高度。 网上有很多监听软键盘弹出的方,但大多用过于复杂或存在缺陷,因此今天我们来聊聊如何简单的监听软键盘弹出并获取软键盘高度。 上面已经提到了,软键盘弹出后 APP 窗口的高度会发生改变,而高度改变必然会导致 View 的 onSizeChanged 方被调用,因此我们可...
android 报这个错,答案 升级到1.3.0-alpha02 implementation ‘androidx.appcompat:appcompat:1.3.0-alpha02’, 多谢老哥: https://blog.csdn.net/yinxing2008/article/details/88189302,下面的回复: 我找到解决方了,链接是开源中国的:https://my.oschina.net/zstorm/blog/4549578 解决方案:修改app/build.gradle中的app
开发语言:java 开发环境:android studio Chipmunk 2021.2.1版本 内容概要:谷歌拼音输入,支持中英文切换。C++代码,cmake编译通过,整个工程可以编译成一个输入apk,安装后需要在设置里添加此输入,再选择使用即可。 适合人群:C++/JAVA开发者,对有输入定制需求的人群
可能大伙儿都发现了Android中并没有直接提供给我们获取输入高度的方,但是接下来提供的方却能帮我们间接获取输入高度。直接上代码 rl_finance_detail.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() {
通常只要有EditText或者其他可输入的控件,在获得焦点时会弹出系统的软键盘,因此可能会导致屏幕产生挤压,控件排列也变形了,解决办AndroidManifest.xml文件中,找到指定的Activity添加属性: android:windowSoftInputMode="adjustResize|adjustPan"
当我们在使用Android设备时,可能会遇到一个问题,就是当输入弹出时,布局会跟着往上移动,导致页面中的其他元素也会向上移动或遮盖住输入框,给用户使用造成一些不便。 这个问题的解决方有很多,包括修改AndroidManifest文件中的配置、设置Activity的属性等等。下面我来介绍一种常见的解决方式。 一般来说,我们可以在xml布局文件中,为根布局添加一个属性:android:fitsSystemWindows="true" 。这样就可以让输入弹出时,布局不再向上移动,而是保持原样。 另外,我们还可以在Activity的onCreate()方中,加入以下代码: getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); 这样就可以让软键盘弹出时,布局不上移,而是直接覆盖输入框下方原有的内容,保持页面的稳定。 总之,无论是在xml布局文件中设置属性,还是在代码中设置软键盘弹出方式,都可以有效地解决Android输入弹出把布局顶上去的问题。