标记WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS不适用于WindowManager.LayoutParams.TYPE_SYSTEM_ERROR

时间:2017-04-16 21:50:33

标签: android layoutparams android-windowmanager

我正在尝试在锁屏上显示视图,并希望能够部分显示它(例如,当视图处于“非活动状态”时,视图的一半在屏幕外)。 br />对于herehere所述类型WindowManager.LayoutParams.TYPE_SYSTEM_ERROR(以及其他一些建议使用此标志的帖子),我可以在锁屏上显示它。但是与标志WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS一起似乎不适用于API级别21。

代码:

WindowManager.LayoutParams params = new 
    WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, 
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | 
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | 
    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSPARENT);

但经过一些测试后,WindowManager.LayoutParams.TYPE_SYSTEM_ERROR类型和旗帜WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS的组合在Android API级别16上有效,但在第21级无效。它只是保持边缘的一侧而不会脱落-屏幕。我也试过设置horizo​​ntalmargin属性,但没有用。

结果不同:

API level 16 (working)

API level 21 (not working)

添加视图的代码(精简版):

layout = (RelativeLayout) getLayoutInflater().inflate(R.layout.testlayout, null).findViewById(R.id.rl);
params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSPARENT);
params.x = 600;
manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
manager.addView(layout, params);

这是一个错误还是其他什么?有没有解决方法,如果有的话?

Q&安培; A:

  

这两个屏幕具有相同的尺寸,分辨率和密度吗?

分辨率是,尺寸号,密度也没有。

  

如果稍微增加水平偏移量(params.x值),那么apis 16和21都会向右移动吗?

在API级别16上它向右移动了一点,但是在21级它只是保持在右侧并且什么都不做。

更新

我看过另一款应用,他们能够实现这一目标(参见this gif)。我反编译他们的apk看看他们的源代码,我发现有关LayoutParams的唯一方法是:

private LayoutParams getLayoutParams() {
    LayoutParams params = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, this.lockscreen ? 2010 : 2002, 262696, -3);
    if (this.focusable) {
        params.flags ^= 8;
    }
    params.gravity = 8388659;
    if (this.keyboard) {
        params.softInputMode = 16;
    }
    return params;
}

this.lockscreen是一个布尔值,它是否应显示在锁屏上

2010WindowManager.LayoutParams.TYPE_SYSTEM_ERRORhttps://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#TYPE_SYSTEM_ERROR

2002WindowManager.LayoutParams.TYPE_PHONE,  试过这个并且不能在锁屏(https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#TYPE_PHONE)左

上工作

262696 flags = 0x40228 = FLAG_WATCH_OUTSIDE_TOUCH, FLAG_LAYOUT_NO_LIMITS, FLAG_NOT_TOUCH_MODAL, FLAG_NOT_FOCUSABLE

-3PixelFormat.TRANSLUCENThttps://developer.android.com/reference/android/graphics/PixelFormat.html#TRANSLUCENT

所以我真的很想知道他们是如何实现这一点的,因为他们似乎也使用了类型WindowManager.LayoutParams.TYPE_SYSTEM_ERROR

1 个答案:

答案 0 :(得分:2)

这可能是不可能的......

我发现了blog post

  

在Android 4.4中,此行为已更改。实际上,此更改会禁用FLAG_LAYOUT_NO_LIMITS Windows的TYPE_SYSTEM_ERROR。这使得用户应用程序无法再在显示的导航栏上放置窗口。

引用此Android source code commit。提交消息指出:

Limit TYPE_SYSTEM_ERROR to system decor bounds.

Because windows of TYPE_SYTEM_ERROR lie in a layer above the
Navigation Bar they cannot be allowed to extend into the Navigation
Bar area or it will block touches to the Home button.

Fixes bug 9626315

和一段差异显示:

- if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
+ // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
+ if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) {

在API 19之后,你必须找到另一种方式。也许是另一种窗口类型,或者以更严格的方式处理视图边界。