1

スクロールイベントとクリックイベントが機能する次のレイアウトを設定したいと思います。

私の 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>

要素の幅は実行時に設定されます。ここで、私の実際のコンテンツは Drawer のハンドルにあり、コンテンツはダミーにすぎないことを言及する必要があります。ハンドルを隠すことができなかったので、このようにしています。または非表示にします。そのため、スワイプしたい場合は、ハンドル (コンテンツ) に触れて引っ張ります。SlidingDrawer では、ハンドルは CustomListView を含むフラグメントのプレースホルダーです。現在の動作: SlidingDrawer をスクロールできます。

取得したい動作: SlidingDrawer では、MotionEvents が X 軸方向 (垂直スワイプ) で検出されます。Y 軸方向の MotionEvent が検出された場合、イベントは CustomListView に送られます。onClicks でさえ ListView にパススルーする必要があります。

私が試したこと: 私はたくさん読みました:こここのページ、そしてこのページ 次に、すべてのナビゲーション コントロールをメイン アクティビティに配置しようとしました。

主な活動:

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

しかし、ここで「isVerticalSwipe」をローカルとして返そうとすると、SlidingDrawer が正しく機能しなくなります。:-( 2 番目の試行は、カスタム スライド ドロワーでタッチ イベントをインターセプトすることでした:

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

ここでは DOWN イベントのみが発生し、MOVE イベントには到達しません。「dispatchTouchEvent」も試してみましたが、成功しませんでした。
イベントがビューの「レイヤー」を上から下に通過することはわかっています。したがって、CustomSlidingDrawer (= トップ ビュー) で上記の最初のリンクから構成を実装する方法と、垂直スワイプが検出されたときにそれを保持して処理し、それが水平スワイプの場合は、に送信してください。 CustomListView を開き、そこでイベントを実行します。

ヘルプ、考え、アイデア、またはコード スニペットを歓迎します。:) ありがとうございました!

[編集]

私はいくつかの進歩を遂げました。イベントを SlidingDrawer から ListView に取得します。リストをスクロールしてクリックすることができます - それはうまくいきます。しかし、残念ながら、SlidingDrawer はもう反応を示しません。これらの行は、私のカスタム 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;
        }
    }
}

なぜ機能しないのかよくわかりません。x 方向にスワイプした場合、Drawer がジェスチャを処理する必要があります。bc は true を返します。代わりに、すべてのイベントが ListView に転送されます。「onInterceptTouchEvent」の前に「dispatchTouchEvent」を実行しようとしましたが、成功しませんでした。ビューを指で移動するために SlidingDrawer を使用する代わりに、より良い解決策があるのではないでしょうか?

4

1 に答える 1

0

さて、たくさんの涙、汗、血の後、私はついに私に合った解決策を見つけました.SlidingDrawerをもう使用せず、LayoutParamsを変更してレイアウトを移動します. 「dispatchTouchEvent」を介して、リストにアクセスできます。

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

そして私の GestureDetector では、オーバーライドされた onScroll-function でレイアウトの変換を処理します。誰かが検出器を必要としている場合は、遠慮なく尋ねてください。共有します.

于 2012-10-17T15:00:11.930 に答える