【发布时间】:2013-03-11 23:12:53
【问题描述】:
如果我有一个显示在用户壁纸上方的活动,有什么方法可以阻止壁纸接收我已经处理过的触摸事件?从 onTouchEvent 返回 true 或 false 似乎没有区别。
【问题讨论】:
标签: android live-wallpaper touch-event
如果我有一个显示在用户壁纸上方的活动,有什么方法可以阻止壁纸接收我已经处理过的触摸事件?从 onTouchEvent 返回 true 或 false 似乎没有区别。
【问题讨论】:
标签: android live-wallpaper touch-event
我想通了!
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);
}
动态壁纸必须满足四个条件才能接收触摸事件:
srcWin(注定要接收触摸的窗口)必须为非空。我不知道这个检查什么时候会失败,但我认为可以肯定地认为这不是一个解决方案。ACTION_DOWN 才能执行这些检查。如果初始向下已被转发到壁纸,其他代码会将触摸事件转发到壁纸,而无需进行所有这些检查。也不是解决方案。mWallpaperTarget,壁纸正在显示的窗口,必须等于srcWin,触摸的目标窗口。TYPE_KEYGUARD,因此这不是解决方案。那么诀窍就是在上面简单地分层另一个窗口!因此,我们现在有一个按此顺序排列的窗口:
mWallpaperTarget,具有@android:style/Theme.Holo.Wallpaper.NoTitleBar 或类似名称。srcWin,PopupWindow
由于 Android 只检查严格相等,并且mWallpaperTarget != srcWin,触摸不会转发到壁纸,并且不允许交互。
【讨论】: