2013-03-11 102 views
0

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

回答

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. 该窗口不得是keyguard。由于Android不再允许非系统应用使用TYPE_KEYGUARD,因此这不是解决方案。

然后,诀窍就是将另一个窗口层叠在上面!因此,我们现在有窗户的顺序栈:

  • 壁纸窗口
  • 活动窗口,mWallpaperTarget,其中有@android:style/Theme.Holo.Wallpaper.NoTitleBar或similiar。
  • srcWin,该PopupWindow

由于Android只检查严格的平等,mWallpaperTarget!= srcWin,触摸被不转发到壁纸,而不是允许的交互。