0

如果我有一个显示在用户壁纸上方的活​​动,有什么方法可以阻止壁纸接收我已经处理的触摸事件?从 onTouchEvent 返回 true 或 false 似乎没有区别。

4

1 回答 1

1

我想通了!

private View empty;

@Override public void onCreate(Bundle savedState)
{
    super.onCreate(savedState);
    empty = new View(this);
    setContentView(empty);
}

@Override public void onAttachedToWindow()
{
    View topview = getLayoutInflater().inflate(R.layout.mylayout, null);
    PopupWindow pw = new PopupWindow(topview);
    pw.setWindowLayoutMode(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    pw.showAtLocation(empty, 0, 0, 0);
}

关键见解来自研究WindowManagerService.java的源代码;具体来说,这部分:

if (srcWin != null
    && pointer.getAction() == MotionEvent.ACTION_DOWN
    && mWallpaperTarget == srcWin
    && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
        sendPointerToWallpaperLocked(relWin, pointer, eventTime);
}

动态壁纸必须满足以下四个条件才能接收触摸事件:

  1. srcWin(注定要接收触摸的窗口)必须是非空的。我不知道这个检查什么时候会失败,但我认为可以安全地假设这不是一个解决方案。
  2. 事件必须是ACTION_DOWN为了执行这些检查。如果初始向下已被转发到壁纸,其他代码会将触摸事件转发到壁纸,而无需进行所有这些检查。也不是解决办法。
  3. mWallpaperTarget, 壁纸正在下方显示的窗口, 必须等于srcWin, 触摸的目标窗口。
  4. 窗户不能是键卫。由于 Android 不再允许非系统应用程序使用TYPE_KEYGUARD,这不是一个解决方案。

那么诀窍就是在顶部简单地分层另一个窗口!因此,我们现在有一个按以下顺序排列的窗口:

  • 壁纸 窗口
  • mWallpaperTarget具有@android:style/Theme.Holo.Wallpaper.NoTitleBar或类似的活动窗口。
  • srcWin, 这PopupWindow

由于 Android 只检查严格相等,并且mWallpaperTarget!= srcWin,触摸不会转发到壁纸,并且不允许交互。

于 2013-04-12T19:08:58.447 回答