拦截动态壁纸触摸事件?

时间:2013-03-11 23:12:53

标签: android live-wallpaper ontouchevent

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

1 个答案:

答案 0 :(得分: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(预定接收触摸的窗口)必须为非null。我不知道这次检查何时会失败,但我认为可以安全地假设这不是一个解决方案。
  2. 要执行这些检查,事件必须为ACTION_DOWN。如果初始向下已经转发到壁纸,则其他代码将触摸事件转发到壁纸而不用打扰所有这些检查。也不是解决方案。
  3. mWallpaperTarget,壁纸显示在下方的窗口必须等于srcWin,即触摸所需的窗口。
  4. 窗户不能成为键盘。由于Android不再允许非系统应用使用TYPE_KEYGUARD,因此这不是解决方案。
  5. 然后诀窍是简单地将另一个窗口叠加在上面!因此,我们现在按顺序拥有一堆窗口:

    • 壁纸窗口
    • 活动窗口mWallpaperTarget,其中包含@android:style/Theme.Holo.Wallpaper.NoTitleBar或类似的内容。
    • srcWinPopupWindow

    由于Android仅检查严格的相等性,mWallpaperTarget!= srcWin,因此触摸不会转发到壁纸,也不允许进行互动。