11

更新: 拡張された質問については報奨金を参照してください。

GestureDetectorセットアップがありますListView。ListView は、ウィンドウの側面から来るフラグメント全体であり、別のフラグメントを部分的にオーバーレイします。ユーザーがスワイプして閉じる機能を提供したいと考えています (つまり、Wunderlist は右側のこの機能の好例です)。

これが私のセットアップです:

    gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {

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

            return false;
        }
    };
    listView.setOnTouchListener(gestureListener); 

リスナー自体:

public class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_MIN_DISTANCE = 180;
        private static final int SWIPE_THRESHOLD_VELOCITY = 50;

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {

            try {
                if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

                    FragmentManager fma = getActivity()
                            .getSupportFragmentManager();



                    FragmentManager fm = getFragmentManager();
                    FragmentTransaction t = fm.beginTransaction();

                    SherlockListFragment mFrag = new RateReviewFragment();

                    t.add(R.id.main_frag, mFrag);
                    t.setCustomAnimations(R.anim.animation_enter,
                            R.anim.animation_leave);
                    t.remove(mFrag);
                    t.commit();

                }
                return false;
            } catch (Exception e) {

            }
            return false;
        }





        @Override
        public void onLongPress(MotionEvent e) {

            // edited out; this opens up a context menu
        }

    }

場合によってはListView、一番下までスクロールすると (またはリストの行をクリックしてリストのスクロールが中断された場合)、GestureListener単純に停止します...リッスンします。スワイプは機能しません。再び機能させるには、スクロールして一番上に戻る必要があります。

誰かがこれらの問題を特定するのを手伝ってくれるなら、私は感謝します!

更新:「リスナーがリッスンを停止する」という問題が1つだけ残っています

更新 2: 何が原因かはわかったかもしれません。修正がわからないだけです:

自分の行動を記録した後、何かを発見しました。リストの下位に行くほど (そして操作するほど)、測定値に一貫性がなくなります。たとえば、リストの一番上で指を左右に 1 cm 動かすと、たとえば 200 ピクセル移動したと表示されます。しかし、私が上記の問題を抱えている場合、同じ1 センチメートルの距離では、はるかに低く、おそらく 50 です。if私の条件を満たしていないので、ウィンドウは閉じません。

補足: 何度も述べましたが、問題は「リストとやり取りする」ときです。つまり、上から下にすばやくスクロールすると、問題ない; しかし、おそらく画面をタップしたり、スクロールをオンまたはオフにしたり、 のボタンをクリックしたりして、ゆっくりと下に向かって作業するとlistView、新しいアクティビティが開きます (その後、同じ位置に戻る)。

4

5 に答える 5

3

これを試して、

    gestureDetector = new GestureDetector(getActivity(),
            new GestureListener());
    View.OnTouchListener gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
           listView.onTouchEvent(event);
           gestureDetector.onTouchEvent(event);

            return true;
        }
    };
    listView.setOnTouchListener(gestureListener);

そして、次の変更を行います

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
  return true;
}

編集: アプリの wunderlist を見ました。その機能をシミュレートしたい場合は、このアプローチを試してください。

ルート レイアウト (listView はその子) に onInterceptTouch を使用します。このメソッド内では、ユーザーがスワイプしたかどうかを次のように確認する必要があります。

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
  if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    if(/* Check your condition here */) { 
      // User has swiped 
      return true;
    }
  }

  return false; // return false so that the event will be passed to child views.
}

詳細についてはAndroid onInterceptTouchEvent

于 2013-06-14T13:19:09.423 に答える
2

onTouch を次のように変更します。

@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
     boolean consumed = gestureDetector.onTouchEvent(event);
     if (event.getAction() == MotionEvent.ACTION_MOVE) {
                return false;
     }

    return consumed;
}
于 2013-06-10T07:23:25.563 に答える
1

初め

trueジェスチャ リスナーでは、 を返すことに注意してくださいonDown。私があなたの質問を正しく理解していれば、タップと垂直スワイプのイベントをListView.

興味のないすべての機能を削除して、興味のないものをすべてに残してはListViewどうでしょうか? それらが必要な場合は、少なくとも returnfalseがデフォルトです (こちらを参照)。

余談ですが、(の親)のコードは、タップとスワイプを処理するためのかなり複雑な状態システムを示しているため、私の見解では、おそらくできるだけ手を加えないでおくのが最善ですAbsListViewListView

第二に

あなたの最近の観察を考えると、おそらく重要なのは、スワイプの絶対サイズではなく、X と Y の変位の比率を考慮することです。報告されたスワイプのサイズの変化を説明することはできませんが、私たちが本当に興味を持っているのは、主に水平方向の動きです。

(change in X) >> (change in Y)

これは次のようにして実現できます。

if ((velocityY == 0.0f) || (Math.abs(velocityX/velocityY) > 3.0f) {
    // The movement is predominantly horizontal
    // Put other checks here (like direction and so on)
    // Then do the stuff
}

e1これにはorを使用しないという利点がありe2ます。

第三に

お気づきのように、問題はリストビューを操作したときです。この時点で、 に複数のポインターが報告されている可能性がありますEvent。それらによって返されるデフォルトの X および Y 情報が特定のポインタ イベントに関連しているとは限りません。次のようなものを使用して、X と Y を含む計算を行いたい場合は、同じポインター イベントからの情報を比較していることを確認する価値があるでしょう。

int numPointers = e1.getPointerCount();
for (int pointerIndex1 = 0; pointerIndex1 < numPointers; pointerIndex1++) {
    int pointerId = e1.getPointerId(pointerIndex1);
    // find index for pointerId in e2.

    float deltaX = e2.getX(pointerIndex2) - e1.getX(pointerIndex1);
    // and so on
}
于 2013-06-16T21:03:34.847 に答える
0

まず、次のようにしてみてくださいOnTouchListener

View.OnTouchListener gestureListener = new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
    gestureDetector.onTouchEvent(event);
        return true;
    }
};

それから - あなたはいつも に戻っfalseてきonFling()ます。節trueで返す。そして、内部のelse節でtry/catch同じデータをメソッドに渡してみてください。onScrollonFling

于 2013-06-16T14:18:26.743 に答える