Android 判断虚拟导航栏是否存在

当我们需要确定设备是否存在虚拟导航栏时,可以借助 Android 系统层面的技术来实现。虚拟导航栏本质上也是一个 View,在布局中绘制并显示在窗口布局中。因此,我们可以通过分析布局层级找到代表虚拟导航栏的 View,并验证其是否存在来判断虚拟导航栏的存在。

首先,我们可以使用 Android Studio 提供的 Layout Inspector 工具来分析应用的布局层级。通常情况下,虚拟导航栏的 View 是 DecorView 的子 View(在 Android 5.0 以上的版本中是这样)。在 DecorView 中找到代表虚拟导航栏的 View 后,我们就可以继续验证其是否存在。

以下是通过代码实现这一过程的示例:

private static final String NAVIGATION = "navigationBarBackground";

/**
 * 判断设备是否存在导航栏。
 * 注意:此方法需要在视图完全绘制出来之后调用,否则无法准确判断。
 * 例如,在 onWindowFocusChanged() 方法中调用可以得到正确的结果。
 *
 * @param activity 当前活动
 * @return 如果存在导航栏则返回 true,否则返回 false
 */
public static boolean isNavigationBarExist(@NonNull Activity activity) {
    // 获取窗口的 DecorView
    ViewGroup vp = (ViewGroup) activity.getWindow().getDecorView();
    
    // 遍历 DecorView 的子 View,寻找导航栏的 View
    if (vp != null) {
        for (int i = 0; i < vp.getChildCount(); i++) {
            // 获取当前子 View
            View childView = vp.getChildAt(i);
            
            // 判断当前子 View 是否是导航栏的背景 View
            if (childView.getId() != View.NO_ID && NAVIGATION.equals(activity.getResources().getResourceEntryName(childView.getId()))) {
                return true; // 如果是导航栏背景 View,则表示存在导航栏
            }
        }
    }
    return false; // 未找到导航栏背景 View,表示不存在导航栏
}

还有另一种方法:

/**
 * 判断设备是否存在导航栏,并回调导航栏状态。
 * 注意:此方法需要在视图完全绘制出来之后调用,否则无法准确判断。
 *
 * @param activity              当前活动
 * @param onNavigationStateListener 导航栏状态监听器
 */
public static void isNavigationBarExist(Activity activity, final OnNavigationStateListener onNavigationStateListener) {
    if (activity == null) {
        return;
    }
    
    // 获取导航栏高度
    final int height = getNavigationHeight(activity);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
        // 设置窗口 DecorView 的 OnApplyWindowInsetsListener,监听窗口变化
        activity.getWindow().getDecorView().setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
            @Override
            public WindowInsets onApplyWindowInsets(View v, WindowInsets windowInsets) {
                boolean isShowing = false;
                int b = 0;
                // 判断窗口变化是否涉及到系统窗口底部的插入(即导航栏)
                if (windowInsets != null) {
                    b = windowInsets.getSystemWindowInsetBottom();
                    isShowing = (b == height);
                }
                // 回调导航栏状态
                if (onNavigationStateListener != null && b <= height) {
                    onNavigationStateListener.onNavigationState(isShowing, b);
                }
                return windowInsets;
            }
        });
    } 
}

/**
 * 获取导航栏的高度。
 *
 * @param activity 上下文
 * @return 导航栏高度,单位为像素
 */
public static int getNavigationHeight(Context activity) {
    if (activity == null) {
        return 0;
    }
    // 获取系统资源
    Resources resources = activity.getResources();
    // 获取导航栏高度资源标识符
    int resourceId = resources.getIdentifier("navigation_bar_height",
            "dimen", "android");
    int height = 0;
    if (resourceId > 0) {
        // 获取导航栏高度
        height = resources.getDimensionPixelSize(resourceId);
    }
    return height;
}

/**
 * 导航栏状态监听器接口。
 */
public interface OnNavigationStateListener {
    /**
     * 导航栏状态回调方法。
     *
     * @param isShowing 导航栏是否显示
     * @param height    导航栏高度
     */
    void onNavigationState(boolean isShowing, int height);
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇