Androidジェスチャー学習のワンポイントジェスチャー


最終更新:2012-03-20
参考自:『Androidモバイル開発1冊で十分』
前述のように、androidは早くから、android 2にサポートされていた.2マルチタッチのサポートを開始する.
異なる動作シーケンスを合わせて異なるジェスチャーを表す.例えばFlingジェスチャーには3つのプロセスがあります.指をスクリーンに押して、すばやくスキャンして、最後に
指を持ち上げる、指を持ち上げるも動き続ける(すなわち、指を持ち上げる前に、動きの速度は減少しない).各ステップの操作によって、対応するイベントがトリガーされます.
Viewコントロールでは、開発者は通常のクリックイベントを処理するときにsetOnClickListener()とsetOnLongClickListener()を使用できます.
方法は同じようにジェスチャーを処理します.onTouchEvent()コールバックメソッドは、View領域内のユーザ動作を検出するために使用される.
onTouchEvent()コールバックメソッドは、1つのパラメータのみを受信します.MotionEventオブジェクト.MotionEventオブジェクトには、View内でトリガーされるすべてのタイプのアクションが含まれます.
の詳細は、連続したMotionEventオブジェクトを収集して分析することで、開発者はどのようなジェスチャーが発生したかを決定することができます.MotionEventデータを使用できます
想像できるジェスチャーを識別しますしかし、Android SDKに内蔵されたジェスチャープローブを使用して、一般的なユーザーの動作を検出することもできます.
Androidには現在、ジェスチャー検出のための2つの異なるクラスがあります.
(1)GestureDetectorクラスは、一般的な単一タッチジェスチャーを検出するために使用することができる.
(2)ScaleGestureDetectorは、マルチポイントスケーリング動作ジェスチャーを検出するために使用することができる.
通常の方向性ジェスチャーに加えて、API level 4に導入されたandroidを使用することもできます.GestureパッケージのGestureOverlayViewは、コマンドジェスチャーを識別します.
 
以下は主に普通の単点タッチジェスチャーを処理します
APIレベル1に導入されたGestureDetectorクラスは、単一のジェスチャーを検出するために使用することができる.GestureDetectorクラスでサポートされている単一指ジェスチャーには、次のようなものがあります.
onDown:ユーザーが画面を初めて押すとトリガーされます.
onShowPress:ユーザーがタッチスクリーンを押し、指を持ち上げたり移動したりする前にトリガー:タッチイベントが検出されたことを表示するために使用されます.
onSingleTapUp:クリック(sinlge-tap)イベントの一部として、ユーザがタッチパネルから指を持ち上げる(持ち上げるMotionEventを使用する)ときにトリガーされます.
onSingleTabConfirmed:イベント発生時に呼び出すをクリックします.
onDoubleTab:ダブルクリック(double-tap)イベント発生時に呼び出されます.
onDoubleTabEvent:ダブルクリックジェスチャーが発生したときに呼び出され、押下(down)、移動、または持ち上げ(up)MotionEventを含む.
onLongPress:onSingleTapUpと似ていますが、ユーザーがタッチ状態を維持し、一定時間移動せず、標準的なクリック操作ではない場合にのみ呼び出されます.
onScroll:ユーザが指を押して指を均等に動かした後、指を持ち上げる前に呼び出す.一般に「ドラッグ」(dragging)ともいう.
onFling:ユーザが指を押して加速させて移動した後、指を持ち上げる前に呼び出され、通常は「フリックジェスチャー」とも呼ばれる.
ヒント:GestureDetectorを使用できます.SimpleOnGestureListenerクラスは、GestureDetectorによって識別された任意のジェスチャーをリスニングする.
 
例:Androidで画像の左右スライド効果を実現.
参照先:
http://www.cnblogs.com/hanyonglu/archive/2012/02/13/2349827.html
原文は比較的詳細で、ここでは回転しません.注意すべき点は、それらの不要な方法を持たないために、SimpleOnGestureListenerクラスを継承することができることです.
個人的な感想を言います.
1.いくつかのネット上の不正確な文章を受けて、OnTouchListenerを実習しました.
結果として、本来はGestureDetectorを書き換えるべきだった.OnGestureListenerインタフェースの
onTouchEventメソッドは、onTouch()メソッドを実现し、私はいつも効果が见えないので、ここで、そこで调べて、结果、その本を探して勉强を始めました.
システムを勉強してから、ソースコードを見ます.GestureDetectorクラスのようなjavadocが見つかりました.
/** 
* To use this class:
 * <ul>
 *  <li>Create an instance of the {@code GestureDetector} for your {@link View}
 *  <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
 *          {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback
 *          will be executed when the events occur.
 * </ul>
**/

上のensureは実現したかどうかをチェックすべきだと思います.そして、結果が出てきました.ははは.うっかりしました.
ジェスチャー効果を判断するコードについて:
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT);
 if (e1.getX() - e2.getX() > 120) {
            this.mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
            this.mFlipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out));
this.mFlipper.showNext();
 return true;
 }

1.イベントがトリガーされたとき、Toastアラートコードが書かれていましたが、実際にはユーザーには見えません.
2.第2の上でジェスチャー距離を判断するには120 pxが少し長い.
 
次に、その中で重要な役割を果たす別のクラスを学びます.ViewFlipper.
ViewFlipperのクラス継承関係は次のとおりです.
ViewFlipper->ViewAnimator->FrameLayout->ViewGroup->View->Object
(中国語翻訳はAndroid中国語翻訳グループから)
/**
 * Simple {@link ViewAnimator} that will animate between two or more views
 * that have been added to it.  Only one child is shown at a time.  If
 * requested, can automatically flip between each child at a regular interval.
 *
    ViewFlipper                      ViewAnimator  。
           。    ,                      。
(   :com.example.android.apis.view/Animation_2.java        )

 * @attr ref android.R.styleable#ViewFlipper_flipInterval
 * @attr ref android.R.styleable#ViewFlipper_autoStart
 */

SimpleOnGestureListenerクラスを使用したJavaコードは次のとおりです.
package me.banxi.slideapp;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.ViewFlipper;

public class SlideAndGestureActivity extends Activity {
	private ViewFlipper mFlipper;
	private GestureDetector mDetector;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.slide);
        
        mDetector = new GestureDetector(getApplicationContext(),new FlingListener());
        mFlipper = (ViewFlipper	)findViewById(R.id.viewFlipper1);
        
        mFlipper.addView(addTextView(R.drawable.one));
        mFlipper.addView(addTextView(R.drawable.two));
        mFlipper.addView(addTextView(R.drawable.three));
        mFlipper.addView(addTextView(R.drawable.four));
        mFlipper.addView(addTextView(R.drawable.five));
        
    }
    
    private View addTextView(int resId){
    	ImageView view = new ImageView(this);
    	view.setImageResource(resId);
    	return view;
    }
    
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return mDetector.onTouchEvent(event);
	}
	
	private class FlingListener extends GestureDetector.SimpleOnGestureListener{
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			String msg = "e1:"+e1.getX()+","+e1.getY()+"e2:"+e2.getX()+","+e2.getY();
			Log.i("MotionSlide", msg);
	        if (e1.getX() - e2.getX() > 120) {
	            mFlipper.setInAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_in));
	            mFlipper.setOutAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_left_out));
	            mFlipper.showNext();
	            return true;
	        } else if (e1.getX() - e2.getX() < -120) {
	            mFlipper.setInAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_in));
	            mFlipper.setOutAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.push_right_out));
	            mFlipper.showPrevious();
	            return true;
	        }
	        return false;
		}	
		
	}

}

 
実際のプロジェクト開発では、このような問題に直面します.
たとえば.上記の例で追加したImageViewのデフォルトでは、イベントは処理されない場合があります.だから正常にスライドできます.
しかし、私の実際の開発では、ViewFlipperの上にGridViewがあり、GridViewの上にButtonが並んでいることがわかりました.そしてスライドジェスチャー
のイベントはViewFlipperには広がらないでしょう.そこで私はGridViewにmarginを設定しました
margin領域でスライドイベントがViwFlipperに渡されます.(厳密にはmDetecotor.onTouchEvent()で行くべきです.
そして私はこの事件の伝播の問題を考えて、それから私は実は主にmDetecotorを呼び出した時、
ActivityのOnTouchEvent(MotionEvent)メソッドでもあります.
このMotionEventイベントをこのようにreturn mDetector.onTouchEvent(event)メソッド処理は戻ります.
そこでbuttonでイベント中のACTION_MOVEでもmDetectorを呼び出す.OnTouchEvent()
でも結果はだめです.その後私はACTIONを区別しませんでしたMOVE待って.
そこで、最後にbuttonとgridViewについて次のように処理しました.
button.setOnTouchListener(new OnTouchListener() {
	@Override
	public boolean onTouch(View v, MotionEvent event) {
	      return mDetector.onTouchEvent(event);

	}
});
gridView.setOnTouchListener(new OnTouchListener() {
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		return mDetector.onTouchEvent(event);
	}
});

Fliingのような事件はACTIONだけではないと思います.MOVEには始まりのOnDownなど一連の事件が組み合わされている.