2011-11-29 70 views
6

(请注意,在这个问题上所描述的行为才出现的,因为别的事情看似无关,我们正在做。见the accepted answer变化SlidingDrawer如何响应轨迹球或光标

我们有一个Android的活动有GridViewSlidingDrawerRelativeLayout之内。这个活动响应轨迹球(或光标键)的方式很奇怪。焦点将在GridView中的项目之间移动,但每当光标向GridView方向“移出”时移动。 (例如,当在顶部时向上,在已经在最左边的物品时离开)滑动抽屉打开或关闭。值得注意的是,焦点停留在GridView中的同一个项目上 - 它不会移动到滑动抽屉。

使用轨迹球时,这特别可怕,因为旋转轨迹球经过您的真实目的地将导致滑动抽屉反复打开和关闭。

我们已确定我们可以通过重写onTrackballEvent()来完全关闭轨迹球。我们希望轨迹球和光标在GridView上正常工作,但不会导致滑动抽屉打开或关闭。原则上,我们还希望轨迹球在打开时专注于滑动抽屉的各种内容。

怎么样?

回答

0

事实证明,我们通过愚蠢的无关位导致此问题。我们希望MENU键可以打开和关闭SlidingDrawer。我们通过覆盖onPrepareOptionsMenu()来做到这一点:

public boolean onPrepareOptionsMenu (Menu menu) { 
    slidingDrawer.animateToggle(); 
    return true; 
} 

这工作正常;但事实证明,当菜单不打开时可以调用它。特别是,如果Activity使用setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT),则未处理的按键事件将最终访问该菜单。这包括离屏幕边缘的轨迹球运动。

越少愚蠢的方式获得所需的行为是

public boolean onKeyUp(int keyCode, KeyEvent event) { 
    if(keyCode==KeyEvent.KEYCODE_MENU) { 
     slidingDrawer.animateToggle(); 
    } 
    return super.onKeyUp(keyCode,event); 
} 

同时,我们可以得到轨迹球SlidingDrawer内移动时,它是通过建立SlidingDrawer.OnDrawerOpenListener这就要求

slidingDrawer.getContent().requestFocus(); 
开放

最后,这似乎是个好主意,拨打

slidingDrawer.getHandle().setFocusable(false); 
3

可以考虑创建扩展GridViewSlidingDrawer和使用的onInterceptTouchEventonTouchEvent自定义实现为GridView和自定义视图只是onInterceptTouchEventSlidingDrawer自定义实现。您可能不需要实施这取决于用户交互可在handle

触发您的自定义GridView定制SlidingDrawer,给它这样也许定义的接口:

public interface MyGridViewListener { 
    public boolean shouldPreventScroll(); 
} 

回报,如果您的自定义SlidingDrawer被打开。此返回值将用于确定是否应在GridView上执行操作(对于onInterceptTouchEventonTouchEvent方法)。因此,当打开SlidingDrawer时,在GridView上执行的操作不会触发SlidingDrawer上的任何操作。

活动:

MyGridView gridView = (MyGridView) findViewById(R.id.gridView); 
gridView.setMyGridViewListener(new MyGridViewListener() { 
    @Override 
    public boolean shouldPreventScroll() { 
     return slidingDrawer.isOpened(); 
    } 
}); 

MyCustomGridView:每当一些触摸/跟踪事件的发生GridView shouldIntercept将被调用。

private boolean shouldIntercept() { 
    boolean shouldIntercept = false; 
    if(myGridViewListener != null) { 
     shouldIntercept = myGridViewListener.shouldPreventScroll(); 
    } 
    return shouldIntercept; 
} 
@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    return shouldIntercept() ? true : super.onInterceptTouchEvent(ev); 
} 
@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    return shouldIntercept() ? true : super.onTouchEvent(ev); 
} 
@Override 
public boolean onTrackballEvent(MotionEvent event) { 
    return shouldIntercept() ? true : super.onTrackballEvent(event); 
} 
public MyGridViewListener getMyGridViewListener() { 
    return myGridViewListener; 
} 
public void setMyGridViewListener(
     MyGridViewListener myGridViewListener) { 
    this.myGridViewListener = myGridViewListener; 
} 

我希望这点你在正确的方向,或至少帮助

+0

有用的想法。它给了我一个想法,在自定义的'SlidingDrawer'中重写'open()'并发出一个堆栈跟踪,这导致了在接受的答案中描述的解决方案。 –

1

虽然与自定义滑动抽屉玩弄我的手柄的布局设置为一些奇怪的价值,像

handle.layout(0, 0,0, 0); 

使手柄消失,但拖动从屏幕上仍然打开滑动抽屉,这是我不想要的东西的一侧手指,所以我设置

handle.layout(10000, 10000, 10000, 10000); 

移动到可视区域外,并且不能再通过从屏幕侧面拖动手动拉出抽屉。在查看源代码中确定抽屉滑动的手柄位置后,摆脱手柄,它应该可以解决您的问题。

如果您需要打开/关闭抽屉调用animateOpen()/ animateClose()