1

I would like to set up following layout with working scroll and click events:

My CustomSlidingDrawer.xml:

<com.project.util.CustomSliderDrawer
    android:id="@+id/slidingDrawerHotelList"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:allowSingleTap="false"
    android:content="@+id/content"
    android:handle="@+id/handle"
    android:orientation="horizontal" >

    <RelativeLayout
        android:id="@+id/handle"
        android:layout_width="0dp"
        android:layout_height="match_parent" >

        <RelativeLayout
            android:id="@+id/content"
            android:layout_width="0dp"
            android:layout_height="0dp" >
        </RelativeLayout>
    </RelativeLayout>
</com.project.util.CustomSliderDrawer>

The width of the elements are set during runtime. Here I have to mention, that my real content is in the handle of the Drawer, and the content is only a dummy. I'm doing that in this way, because I was not able to hide the handle. Or make it invisible. So, if I want to swipe in I touch the handle (my content) and pull. In the SlidingDrawer, the handle is a placeholder for a fragment which contains a CustomListView. What now works: I can scroll the SlidingDrawer.

What behavior I would like to gain: On the SlidingDrawer the MotionEvents are detected in X-Axis direction (Vertical swipe). If a MotionEvent in Y-Axis direction is detected, then the Events shoud go to my CustomListView. Even the onClicks should pass through to the ListView.

What I've tried: I read a lot: here, this page and this one Then I tried to put all the navigation control in the main activity, what makes really sense in my eyes:

MainActivity:

slidingDrawer.setOnTouchListener(new OnTouchListener() {
        int downX, downY;

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            int action = event.getAction();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getX();
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = downX - (int) event.getX();
                int deltaY = downY - (int) event.getY();
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    Log.i(TAG, "scrollX direction");
                    isVerticalSwipe = true;
                } else {
                    Log.i(TAG, "scrollY direction");
                    isVerticalSwipe = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
            }
            return false;
        }
    });

But when I try here to return "isVerticalSwipe" as local, the SlidingDrawer works not properly anymore. :-( The 2nd try was to intercept the touch events in the custom sliding drawer:

CustomSlidingDrawer:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
        Log.i(TAG, "onInterceptTouchEvent ACTION_DOWN");
        xDistance = yDistance = 0f;
        downX = (int) ev.getX();
        downY = (int) ev.getY();
        break;
    case MotionEvent.ACTION_MOVE:
        Log.i(TAG, "onInterceptTouchEvent ACTION_MOVE");
        final int curX = (int) ev.getX();
        final int curY = (int) ev.getY();
        xDistance += Math.abs(curX - downX);
        yDistance += Math.abs(curY - downY);
        downX = curX;
        downY = curY;
        if (xDistance > yDistance)
            return false;
    }

    return super.onInterceptTouchEvent(ev);
}

Here happens only the DOWN event and the MOVE event is never reached. I also made some trys with "dispatchTouchEvent" but I got no success.
I know, that the events will pass through the "layer" of my views - from top to bottom. So it would be perfect to know, how I can implement the construct from the first link above in my CustomSlidingDrawer (= top view) and when a vertical swipe is detected keep and handle it and if it's a horizontal swipe, then please send it to the CustomListView and perform there the events.

Any help, thoughts, ideas or code snippets are appreciated. :) Thank you!

[EDIT]

I've made some progress. I get now my events from the SlidingDrawer down to my ListView. I can scroll and click in the list - that works fine. But unfortunately, my SlidingDrawer shows no reaction anymore. These lines are in my custom SlidingDrawer:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    gestureDetector = new GestureDetector(new MyGestureDetector());

    if (gestureDetector.onTouchEvent(event)) {
        return true;

    } else if (event.getAction() == MotionEvent.ACTION_UP
            || event.getAction() == MotionEvent.ACTION_CANCEL) {
        return false;
    } else {
        Log.i(TAG, "gestureDetector returned false");
        return false;
    }
}

class MyGestureDetector extends SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        Log.i(TAG, "onDown");
        downX = (int) e.getX();
        downY = (int) e.getY();
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2,
            float distanceX, float distanceY) {
        float deltaX = downX - e2.getX();
        float deltaY = downY - e2.getY();
        if (Math.abs(deltaX) > Math.abs(deltaY)) {
            Log.i(TAG, "scrollX direction");
            return true;
        } else {
            Log.i(TAG, "scrollY direction");
            return false;
        }
    }
}

I don't really understand why it's not working, if there is a swipe in x-direction, then my Drawer should handle the gesture, bc I return true. Instead every event is forwarded to the ListView. I tried to run "dispatchTouchEvent" before the "onInterceptTouchEvent" but I had no success. Maybe there is a better solution instead of using a SlidingDrawer for moving views by finger?

Community
  • 1
  • 1
Camino2007
  • 796
  • 10
  • 17

1 Answers1

0

Okay, after a lot of tears, sweat and blood I finally found a solution which works for me: I don't take a SlidingDrawer anymore and move my layout via changing the LayoutParams. Over the "dispatchTouchEvent" I get access to my list.

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (mGestureDetector.onTouchEvent(ev)) {
        return true;
    }
    if (ev.getAction() == MotionEvent.ACTION_UP) {
        Log.i(TAG, "ACTION_UP");
        Log.i(TAG, "getLeft: " + getLeft());
        if (getLeft() < 280) {
            // run ani to left
        } else {
            // run ani to right
        }
    }

    return super.dispatchTouchEvent(ev);
}

And in my GestureDetector I handle in the overridden onScroll-function the layout translation. If someone has need for the detector don't hesitate to ask, I'll share.

Camino2007
  • 796
  • 10
  • 17