【问题标题】:Flag WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS does not work with type WindowManager.LayoutParams.TYPE_SYSTEM_ERROR标志 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS 不适用于类型 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
【发布时间】:2017-09-12 13:01:15
【问题描述】:

我正在尝试在锁屏上显示一个视图,并且还希望能够部分显示它(例如,当视图处于“非活动状态”时,一半的视图在屏幕外)。 使用WindowManager.LayoutParams.TYPE_SYSTEM_ERROR 描述的herehere 类型(以及其他一些建议使用此标志的帖子),我可以在锁屏上显示它。但与标志 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);

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

问答:

这两个屏幕的尺寸、分辨率和密度是否相同?

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

如果稍微增加水平偏移(params.x 值),api 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_ERROR (https://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)

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

-3PixelFormat.TRANSLUCENT (https://developer.android.com/reference/android/graphics/PixelFormat.html#TRANSLUCENT)

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

【问题讨论】:

标签: android layoutparams android-windowmanager


【解决方案1】:

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

我找到了这个blog post

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

引用了这个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 开始,您必须找到另一种方法。可能是另一种窗口类型,或者以更严格的方式处理视图边界。

【讨论】:

  • 似乎是它的原因。虽然我看过另一个应用程序,他们能够使用TYPE_SYSTEM_ERROR 来实现这一点(请参阅帖子和 gif 中的更新)并且没有其他窗口类型可以在锁屏上显示包含交互的视图
  • 那么以更严格的方式处理视图边界是什么意思?能举个例子吗?
  • @Denny 这可能会非常费力,但我想检测要添加的视图是否会超出屏幕限制。换句话说,在插入视图之前进行所有计算以检测是否会发生不希望的行为,然后调整视图布局使其不会发生。总之,通过调整视图布局来防止不良行为
  • 使用填充和边距找到了一个丑陋的解决方法,它允许我在锁定时部分显示视图并仍然与之交互。似乎目前没有其他选择。
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
相关资源
最近更新 更多