Android 全局监听软键盘弹起隐藏 动态修改布局并适配无限循环的问题

思路:

要在 Android 应用中全局检测软键盘的弹起,您可以使用 ViewTreeObserver.OnGlobalLayoutListener 监听器来监听布局树的变化。当软键盘弹起或隐藏时,布局树会发生变化,因此您可以在监听器中捕获这些变化。

以下是一个示例,展示如何在全局范围内检测软键盘的弹起:

复制代码
import android.graphics.Rect;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private View rootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rootView = findViewById(R.id.rootView); // Replace with your root layout's ID

        // Register a global layout listener
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                // Get the height of the visible display area
                Rect rect = new Rect();
                rootView.getWindowVisibleDisplayFrame(rect);
                int screenHeight = rootView.getHeight();
                int keyboardHeight = screenHeight - rect.bottom;

                // If the keyboard height is greater than a threshold (e.g., 100 pixels), the keyboard is likely visible
                if (keyboardHeight > 100) {
                    // Keyboard is visible, do something
                } else {
                    // Keyboard is hidden, do something else
                }
            }
        });
    }
}

在上面的代码中,rootView 是您布局的根视图,您需要将其替换为您实际布局的根视图。addOnGlobalLayoutListener 方法用于注册一个监听器,当布局树发生变化时会调用 onGlobalLayout 方法。

onGlobalLayout 方法中,您可以通过比较屏幕高度和可见区域的底部位置来计算软键盘的高度。根据计算结果,您可以判断软键盘是否可见,并执行相应的操作。

以下是一个在项目中的实际示例,解决无限循环的示例:

复制代码
private void changerBottomView() {
        binding.includedNoteMenu.fragmentLl.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
    

private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect rect = new Rect();
            //取得 rootView 可视区域
            binding.includedNoteMenu.fragmentLl.getWindowVisibleDisplayFrame(rect);
            //取得 rootView 不可视区域高度 (被其他View遮挡的区域高度)
            int rootInvisibleHeight = binding.includedNoteMenu.fragmentLl.getRootView().getHeight() - rect.bottom;
            LogUtil.i("shawn","rootInvisibleHeight = " + rootInvisibleHeight);
            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)binding.includedNoteMenu.fragmentLl.getLayoutParams();
            if (layoutParams.bottomMargin != rootInvisibleHeight + UiUtil.dp2px(10)) {
                layoutParams.bottomMargin = rootInvisibleHeight + UiUtil.dp2px(10);
                binding.includedNoteMenu.fragmentLl.setLayoutParams(layoutParams);
            }

        }
    };

日志: 只会多调用一次,在第二次回调时,条件已不满足,不会再调用setLayoutParams

复制代码
I/shawn: [ main: AddNoteFragment.java:173 onGlobalLayout ] - rootInvisibleHeight = 840
I/shawn: [ main: AddNoteFragment.java:173 onGlobalLayout ] - rootInvisibleHeight = 840
I/shawn: [ main: AddNoteFragment.java:173 onGlobalLayout ] - rootInvisibleHeight = -4
I/shawn: [ main: AddNoteFragment.java:173 onGlobalLayout ] - rootInvisibleHeight = -4
相关推荐
雨白11 小时前
Android 快捷方式实战指南:静态、动态与固定快捷方式详解
android
hqk11 小时前
鸿蒙项目实战:手把手带你实现 WanAndroid 布局与交互
android·前端·harmonyos
LING12 小时前
RN容器启动优化实践
android·react native
恋猫de小郭14 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker19 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴19 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭1 天前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab1 天前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe1 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农2 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos