私は Android アプリ開発の初心者で、Android の SimpleOnGestureListener と ViewFlipper を使用してスワイプ ジェスチャをいじっています。ViewFlipper には 3 つの子があり、それぞれが ScrollView です。アクティビティが読み込まれると、それらはすべて動的に入力され、その後は変更されません。ScrollView は、SimpleOnGestureListeners がアタッチされている場所です。
私が使用しているレイアウトは次のとおりです:
+ViewFlipper
++
ScrollView
(x3、各ページに 1 つ、それぞれ次のものを
含む) )
++++見る
オンラインのどこにでもある一般的なチュートリアル コードを使用して onFling メソッドを拡張しました。ScrollViews の 1 つにスクロールするのに十分なコンテンツが含まれていない場合を除いて、うまく機能します。
SimpleOnGestureListener のすべてのメソッドをオーバーライドして super を呼び出し、print-to-log を追加することで、問題をタッチ検出に絞り込みました。
スクロールするページをスワイプすると、「in onClick」「in onScroll」「in onFling」などでいっぱいになります。スクロールするには短すぎるページでは、「in onClick」「in onShowPress」「in onLongPress」になります。 」、そしてそれは、短すぎるスクロールビューの子内のコンテンツに触れている場合のみです-他の場所に触れた場合、イベントはまったく発生しません.
何が問題なのか、またはスクロールビューの大きさに関係なくスワイプジェスチャを検出する方法についてのアイデアはありますか?
編集: これを Android 2.2 エミュレーターで実行すると、私が使用している Android 2.1u1 DroidX エミュレーターとは対照的に、それがなくなることがわかりました。これは、複数の環境で再現可能です。
これについては、もう少し洞察があります。スクロールビューがフリッパー (または WorkspaceView) 内に含まれている場合、すべてのモーション イベントに対して onInterceptTouchEvent が呼び出されないように見えます。
特に、これとまったく同じ問題を修正するために別のビュー クラスを変更しているときに見つけた動作 (フリッパーに固有のものではありません) は次のとおりです。これは Android 2.1 のみであることに注意してください。
スクロールビューがスクロールするのに十分な長さの場合、ACTION_DOWN モーション イベントは ScrollView によってキャッチされ、後続のすべての ACTION_MOVE イベントはフリッパーの onInterceptTouchEvent を通過し、そこでインターセプトされて適切に処理されます。Android 2.2 では、この動作はスクロールの長さに関係なく発生します。
2.1 に戻る: scrollview がスクロールするのに十分な長さでない場合、ACTION_DOWN モーション イベントはscrollview によってキャッチされず、フリッパーの onTouchEvent に戻ります。同じジェスチャの後続のすべての ACTION_MOVE イベントは、onInterceptTouchEvent 関数をスキップして、onTouchEvent 関数に直接進みます。
私がこれを解決した方法は、ACTION_MOVE イベントの onTouchEvent にあった機能を取り、それを独自のメソッドにリファクタリングすることでした。このようにして、イベントが以前に未処理になったことを検出した場合、onTouchEvent で onInterceptTouchEvent を呼び出し、その後にその機能を呼び出すことができます。
case MotionEvent.ACTION_MOVE:
if (touchState == TOUCH_STATE_SCROLLING) {
handleScrollMove(ev);
} else {
// Log.d("workspace","caught a move touch event but not scrolling");
//NOTE: We will never hit this case in Android 2.2. This is to fix a 2.1 bug.
//We need to do the work of interceptTouchEvent here because we don't intercept the move
//on children who don't scroll.
Log.d("workspace","handling move from onTouch");
if(onInterceptTouchEvent(ev) && touchState == TOUCH_STATE_SCROLLING){
handleScrollMove(ev);
}
}
break;
これは WorkspaceView.java からのものです (Android の Workspace.java の変更で、Google コードの andro-views プロジェクトにあり、現在はビュー間の水平方向の「タブ」のようなスクロール)。move イベントを受け取り、スクロールしている場合 (意図的にインターセプトすることを選択した場合にのみ発生します。つまり、インターセプト関数で設定されているため、既にインターセプト関数に行っています)。私たちが望む動きの振る舞い。ここで移動イベントを受け取り、スクロールしていない場合は、onIntercept を介してイベントを送り返し、スクロールするように設定されているかどうかを確認します。その場合は、アクションを実行します。
エレガントではありませんが、機能します。