Android app 获取底部虚拟按键的高度

本文详细介绍了如何在Android应用程序中检测并获取底部虚拟按键的高度,包括必要的代码示例和注意事项,帮助开发者优化界面布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 public static int getVirtualBarHeight(Context context) {
        int vh = 0;
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        try {
            @SuppressWarnings("rawtypes")
            Class c = Class.forName("android.view.Display");
            @SuppressWarnings("unchecked")
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            vh = dm.heightPixels - display.getHeight();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (isMIUI()) {
            if (isFullScreen(context)) {
                vh = 0;
            }
        } else {
            if (!NDUtils.hasDeviceNavigationBar(context)) {
                vh = 0;
            }
        }
        return vh;
    }

 /**
     * 获取是否有虚拟按键
     * 通过判断是否有物理返回键反向判断是否有虚拟按键
     *
     * @param context
     * @return
     */
    public static boolean hasDeviceNavigationBar(Context context) {


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
            Point size = new Point();
            Point realSize = new Point();
            display.getSize(size);
            display.getRealSize(realSize);
            boolean result = realSize.y != size.y;
            return realSize.y != size.y;
        } else {

            boolean menu = ViewConfiguration.get(((Activity) context)).hasPermanentMenuKey();
            boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
            if (menu || back) {
                return false;
            } else {
                return true;
            }
        }
 public static boolean isFullScreen(Context context) {
        // true 是手势,默认是 false
        // https://www.v2ex.com/t/470543
        return Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0) != 0;

    }

    public static boolean isMIUI() {
        String manufacturer = Build.MANUFACTURER;
        // 这个字符串可以自己定义,例如判断华为就填写huawei,魅族就填写meizu
        if ("xiaomi".equalsIgnoreCase(manufacturer)) {
            return true;
        }
        return false;
    }
### Android 中通过应用检测或处理虚拟按键通知的方法 在 Android 开发中,可以利用特定 API 和机制来检测和处理虚拟按键的通知行为。以下是实现这一目标的具体方式: #### 1. **监听虚拟按键的状态变化** 为了捕获虚拟按键的行为,开发者可以在 `View` 或者 `Activity` 的生命周期方法中拦截这些事件。例如,当用户按下返回键时,可以通过重写 `onBackPressed()` 方法来进行干预。 ```java @Override public void onBackPressed() { // 自定义逻辑,比如提示确认对话框或者忽略操作 if (shouldInterceptBackPress()) { showConfirmationDialog(); } else { super.onBackPressed(); // 执行默认的返回操作 } } ``` 这种方法适用于防止误触返回键的情况[^4]。 --- #### 2. **全局监控输入事件** 如果需要更深层次地控制虚拟按键的行为,则可能涉及底层框架中的 `InputManagerService` 和 `WindowManagerPolicy` 组件。具体来说,Android 系统会将所有的输入事件(包括触摸屏、键盘以及导航栏上的虚拟按键)转换为标准化的 `input_event` 数据结构,并传递给相应的处理器[^5]。 对于第三方应用程序而言,虽然无法直接访问系统的 InputPipeline 流程,但仍可通过某些间接手段捕捉部分交互动作。例如,借助 Accessibility Service 来跟踪用户的焦点切换与手势触发路径。 ##### 使用 Accessibility Service 实现虚拟按键监测 创建一个继承自 `AccessibilityService` 的类,并在其回调函数中解析接收到的动作类型。 ```java public class VirtualKeyMonitor extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType(); switch (eventType) { case AccessibilityEvent.TYPE_VIEW_CLICKED: Log.d("VirtualKey", "A view was clicked."); break; default: break; } } @Override public void onInterrupt() {} } ``` 配置文件声明服务权限及过滤条件: ```xml <service android:name=".VirtualKeyMonitor" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService"/> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service> ``` 上述代码允许程序感知屏幕上的点击活动,尽管其精度有限且主要面向辅助功能场景,但它提供了一种可行的技术路线[^3]。 --- #### 3. **动态调整虚拟导航栏可见性** 除了被动接收反馈外,还可以主动修改虚拟按键的表现形式以减少干扰风险。例如,在全屏模式下隐藏底部工具条即可有效降低意外触动概率。 调用以下方法可临时关闭软控件显示效果: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } else { requestWindowFeature(Window.FEATURE_NO_TITLE); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } ``` 注意该策略仅影响当前 Activity 的呈现样式而不改变实际硬件状态[^1]。 --- ### 总结 综上所述,针对 Android 平台下的虚拟按键管理需求,既可以从高层级入手定制 UI 行动序列,也可以深入挖掘操作系统内部运作原理寻求解决方案。然而需要注意的是,出于安全性和隐私保护方面的考量,许多敏感区域已被官方严格封锁,因此建议优先考虑合法合规的方式达成目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值