WindowManager.add查看软键或导航栏的顶部(覆盖)



我今天看到了一个覆盖整个屏幕的应用程序,包括导航栏(或具有返回、主页等功能的软键)。它是CF.Lumen(需要android 4.4+)通过chainfire。

我只记得这在一般方法上是不可能的,很多SO答案告诉我。所以我从Lumens-apk(抱歉,chainfire)中查找了smali代码,发现0x7d6是类型说明符,即TYPE_SYSTEM_OVERLAY。通常,这会使视图覆盖在锁定屏幕的顶部。它看起来不错,但不会覆盖导航栏区域。即使在锁屏上。我确实将MATCH_PARENT替换为9999,但它仍然不会覆盖导航栏区域。

我查阅了安卓的源代码,发现有趣的是有更多的类型没有记录。

FIRstrongYSTEM_WINDOW=2000;

TYPE_NAVIGATION_BAR=FIRstrongYSTEM_WINDOW+19;

TYPE_BOOT_PROGRESS=FIRstrongYSTEM_WINDOW+21;

我把这些应用到了我的应用程序上,但被crashe拒绝了。它需要INTERNAL_SYSTEM_WINDOW或比SYSTEM_ALERT_WINDOW更没有文档的东西。这些权限仅授予系统应用程序。

这是我的代码,添加一个视图填充整个屏幕,除了导航栏区域。

我该怎么做才能使它复杂化?(覆盖包括导航栏区域)

final WindowManager.LayoutParams paramsRL = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            WindowManager.LayoutParams.FLAG_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
            PixelFormat.TRANSLUCENT);
windowManager.addView(view_floating, paramsRL);

下面是一个有效的小例子:

    FrameLayout frameLayout = new FrameLayout(context);
    frameLayout.setBackgroundColor(Color.BLACK);
    frameLayout.setAlpha(0.5f);
    windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                    | WindowManager.LayoutParams.FLAG_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            PixelFormat.TRANSLUCENT);
    //make sure height includes the nav bar size (get the dimension of whole screen)
    params.height = screenHeight;
    params.width = screenWidth;
    windowManager.addView(frameLayout, params);
    //add your view to this frameLayout
    frameLayout.addView(....);

这里有三件关键的事情:

  1. TYPE_SYSTEM_OVERLAY(或任何类似类型),可以在整个屏幕上显示内容。

  2. FLAG_LAYOUT_NO_LIMITS,它允许我们超出允许的正常大小。

  3. 设置软键后面需要覆盖的额外高度。主要的问题是,当我们将参数设置为match_parent时,它设置为屏幕的高度减去导航栏。设置额外的高度解决了这个问题。

不要使用WindowManager.LayoutParams.FLAG_not_FOCUSABLE,此标志将使导航栏始终显示。我不知道为什么。

最新更新