web-dev-qa-db-fra.com

Android: Comment empêcher DrawerLayout de transmettre des événements tactiles à la vue sous-jacente

J'utilise le DrawerLayout de la bibliothèque d'assistance dans mon application. J'ai remarqué que lorsque je clique sur une zone vide de ma vue Tiroir, la vue sous-jacente (contenant un ListView) reçoit l'événement Touch et y réagit.

La méthode onInterceptTouchEvent de DrawerLayout ressemble à ceci:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    final int action = MotionEventCompat.getActionMasked(ev);

    // "|" used deliberately here; both methods should be invoked.
    final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) |
            mRightDragger.shouldInterceptTouchEvent(ev);

    boolean interceptForTap = false;

    switch (action) {
        case MotionEvent.ACTION_DOWN: {
            final float x = ev.getX();
            final float y = ev.getY();
            mInitialMotionX = x;
            mInitialMotionY = y;
            if (mScrimOpacity > 0 &&
                    isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {
                interceptForTap = true;
            }
            mDisallowInterceptRequested = false;
            mChildrenCanceledTouch = false;
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            // If we cross the touch slop, don't perform the delayed peek for an Edge touch.
            if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
                mLeftCallback.removeCallbacks();
                mRightCallback.removeCallbacks();
            }
            break;
        }

        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP: {
            closeDrawers(true);
            mDisallowInterceptRequested = false;
            mChildrenCanceledTouch = false;
        }
    }

    return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
}

Ma vue avec le DrawerLayout:

<Android.support.v4.widget.DrawerLayout
        xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:id="@+id/drawer_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

    <FrameLayout
            Android:id="@+id/content"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"/>

    <FrameLayout
            Android:id="@+id/sidebar_container"
            Android:layout_width="300dp"
            Android:layout_height="match_parent"
            Android:layout_gravity="left"/>

</Android.support.v4.widget.DrawerLayout>

Que puis-je faire (si possible sans étendre la classe DrawerLayout) pour éviter ce problème? Tant que le tiroir est ouvert, je ne souhaite pas que des événements de clic atteignent la vue d'arrière-plan.

45
janoliver

Définissez clickable sur true sur le tiroir - cela consommera le toucher.

<Android.support.v4.widget.DrawerLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <FrameLayout
        Android:id="@+id/content_view"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"/>

    <FrameLayout
        Android:id="@+id/drawer_view"
        Android:layout_width="300dp"
        Android:clickable="true"
        Android:importantForAccessibility="no"
        Android:layout_height="match_parent"
        Android:layout_gravity="left"/>

</Android.support.v4.widget.DrawerLayout>

J'ai ajouté Android:importantForAccessibility="no" car le fait de marquer le tiroir comme interactif (cliquable ou focalisable) rendra le tiroir entier visible aux services d'accessibilité comme TalkBack.

Ce n'est pas ce que vous voulez (généralement) - le plus souvent, les articles à l'intérieur le tiroir doit être accessible aux services.

Cet attribut n'est disponible que sur l'API 16+.

81
ataulm