Изменение реакции SlidingDrawer на трекбол или курсор

(обратите внимание, что поведение, описанное в этом вопросе, появилось только из-за чего-то еще, казалось бы, не связанного с тем, что мы делали. См.принято отвечать.)

у нас есть Android активность с GridView и SlidingDrawer внутри RelativeLayout. То, как это действие реагирует на трекбол (или клавиши курсора), довольно странно. Фокус будет перемещаться между элементами в GridView, но всякий раз, когда курсор перемещается в направлении "из" в GridView. (например, вверх, когда вверху, слева, когда уже в крайнем левом элементе) выдвижной ящик открывается или закрывается. Примечательно, что фокус остается на том же элементе в GridView---он не перемещается в выдвижной ящик.

с трекболом это особенно ужасно, так как вращение трекбола мимо вашего реального места назначения заставит выдвижной ящик неоднократно открываться и закрываться.

мы определили, что мы можем отключить трекбол полностью путем переопределения onTrackballEvent(). Мы бы предпочли, чтобы трекбол и курсор работали нормально на GridView, но не заставляли выдвижной ящик открываться или закрываться. В принципе, мы также хотели бы, чтобы трекбол сосредоточился на различном содержимом выдвижного ящика, когда он открыт.

как?

3 ответов


вы можете создать пользовательский вид, простирающийся GridView и SlidingDrawer и использование пользовательских реализаций onInterceptTouchEvent и onTouchEvent на GridView и пользовательская реализация только для onInterceptTouchEvent на SlidingDrawer. Возможно, Вам не потребуется реализовывать custom SlidingDrawer в зависимости от того, какие пользовательские взаимодействия могут быть вызваны на handle

для вашего custom GridView, дайте ему интерфейс, возможно, определенный следующим образом:

public interface MyGridViewListener {
    public boolean shouldPreventScroll();
}

возврат, если ваш заказ SlidingDrawer is открытый. это возвращаемое значение будет использоваться для определения, следует ли выполнять действия(для onInterceptTouchEvent и onTouchEvent методов) на GridView. Итак, когда SlidingDrawer открывается, действия выполняются на GridView не вызовет ничего, на SlidingDrawer.

действие:

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

MyCustomGridView: shouldIntercept будет вызываться всякий раз, когда какое-либо событие touch/track происходит на GridView.

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;
}

я надеюсь, что это указывает вам на правильное направление или, по крайней мере, помогает


играя с пользовательским выдвижным ящиком, я установил расположение ручки на какое-то нечетное значение, что-то вроде

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

чтобы ручка исчезла, но перетаскивание пальца со стороны экрана все равно откроет выдвижной ящик, чего я не хотел, поэтому я установил

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

который переместил его за пределы видимой области, и ящик больше не мог быть вытащен вручную путем перетаскивания со стороны экрана. Посмотрев на исходный код свое положение ручки которая определяет сползать ящика, получает освобожданным ручки и ее должен разрешить вашу проблему.

Если вам нужно открыть/закрыть ящик, вызовите animateOpen () / animateClose ()


как оказалось, мы вызвали эту проблему из-за несвязанной глупости. Мы хотели меню ключ для открытия и закрытия SlidingDrawer. Мы сделали это, переопределив onPrepareOptionsMenu():

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

это отлично работает; но оказывается, что его можно вызвать, когда меню не будет открыто. В частности, если Activity использует setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT), затем необработанное ключевое событие завершится доступом к меню. Это включает движение trackball от края экран.

менее глупый способ получить желаемое поведение -

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);