Androidで上下スライド効果を実現

6436 ワード

多くの場合、タッチスクリーンのFling、ScrollなどのGesture(ジェスチャー)操作を利用して操作すると、ブラウザでスクリーンをスクロールしたり、Flingでリーダーのページをめくったりするなど、アプリケーションのユーザー体験が大幅に向上します.Androidシステムではジェスチャーの認識はGestureDetector.OnGestureListenerインタフェースで実現されたが、WilliamはAndroidの公式ドキュメントをめくっても関連例が見つからず、API DemoのTouchPaintもonTouchイベントの処理に言及しただけで、ジェスチャーには触れていない.Android Developerディスカッショングループにも私と似たような問題がある人が少なくありません.彼らが言及した方法と私が行った実験を結びつけて、Androidでのジェスチャー認識の実現を簡単に説明します.まずいくつかの概念を明らかにします.まず、Androidのイベント処理メカニズムはListener(Listener)に基づいて実現されています.今日お話ししたタッチスクリーン関連のイベントよりも、onTouchListenerによって実現されています.次に、すべてのViewのサブクラスは、setOnTouchListener()、setOnKeyListener()などの方法で、あるイベントに対するリスナーを追加することができる.第三に、Listenerは一般に、onTouch()、onKey()などの操作を完了するために、1つ以上のabstract(抽象)メソッドを含むインタフェース(インタフェース)方式で提供される.このように、あるviewにイベントListenerを設定し、その抽象的な方法を実現すると、プログラムは、特定のイベントがそのviewにdispatchされたときにcallbakc関数によって適切な応答を与えることができる.簡単な例を見て、最も簡単なTextViewで説明します(実際にはADTで生成されたskeletonと何の違いもありません).
public class GestureTest extends Activity implements OnTouchListener{    

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);    
        setContentView(R.layout.main);    

       // init TextView 
       TextView tv = (TextView) findViewById(R.id.page);    

        // set OnTouchListener on TextView 
        tv.setOnTouchListener(this);    

        // show some text 
        tv.setText(R.string.text);    
}    

@Override
public boolean onTouch(View v, MotionEvent event) {    
         Toast.makeText(this, "onTouch", Toast.LENGTH_SHORT).show();
    return false;    
}  

     
TextViewのインスタンスtvにonTouchListenerを設定したが,GestureTestクラスはOnTouchListenerインタフェースを実現しているので,簡単にthisをパラメータとして与えることができる.onTouchメソッドはOnTouchListenerの抽象的なメソッドを実現し、ここで論理コードを追加すれば、ユーザーが画面に触れるときに応答することができ、ここで行ったように、ヒント情報を出すことができます.
ここでは、ActionEventのgetAction()メソッドを使用して、ACTION_を含むTouchイベントのタイプを取得できます.DOWN, ACTION_MOVE, ACTION_UPとACTION_CANCEL.ACTION_DOWNとは、タッチパネルを押すこと、ACTION_MOVEとは、タッチパネルを押して受力点を移動すること、ACTION_UPとは、タッチパネルを離すこと、ACTION_CANCELはユーザーによって直接トリガーされません(したがって、今日の議論の範囲ではありません.ViewGroup.onInterceptTouchEvent(MotionEvent)を参照してください).ユーザの異なる操作の判断により,getRawX()やgetRawY()やgetX()やgetY()などの手法を組み合わせて座標を取得すると,あるボタンをドラッグしたりスクロールバーをドラッグしたりするなどの機能を実現できる.スタンバイではMotionEvent類の文書を見たり、TouchPaintの例を見たりすることができます.
今日お話しするポイントに戻りますが、Touch操作を捉えたとき、ユーザーのGestureをどのように認識しますか?ここにはGestureDetectorが必要です.OnGestureListenerインタフェースの助けで、私たちのGestureTestクラスはこのようになりました.
public class GestureTest extends Activity implements OnTouchListener,    
         OnGestureListener {    
....    
} 

      
次に、onTouch()メソッドでは、GestureDetectorのonTouchEvent()メソッドを呼び出し、キャプチャされたMotionEventをGestureDetectorに渡して、ユーザのジェスチャーを処理するために適切なcallback関数があるかどうかを分析する.
public boolean onTouch(View v, MotionEvent event) {
    // OnGestureListener will analyzes the given motion event
    return mGestureDetector.onTouchEvent(event);    
}   

     
次に,onFling(),onScroll(),onLongPress()の6つの抽象手法を実現した.私はすでにそれぞれの方法で代表されるジェスチャーの意味を注釈に書いていますが、見てみれば分かります.
ユーザがタッチパネルに軽く触れ、1つのMotionEvent ACTION_DOWNトリガ
@Override  
public boolean onDown(MotionEvent e) {       
  
// TODO Auto-generated method stub    
      Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();       
  
    return false;       
}

 
ユーザーがタッチパネルを軽くタッチし、まだ離したりドラッグしたりしていないので、1つ1つのMotionEvent ACTION_DOWNトリガ注意とonDown()の違いは,緩めたりドラッグしたりしていない状態を強調する.
@Override  
public void onShowPress(MotionEvent e) {       
  
    // TODO Auto-generated method stub    
}

 
ユーザ(タッチパネルを軽くタッチした後)が離し、1つ1つのMotionEvent ACTION_UPトリガ
@Override
public boolean onSingleTapUp(MotionEvent e) {    
    // TODO Auto-generated method stub 
   return false;    
}  

 
ユーザーがタッチパネルを押して、素早く移動してから離し、1つのMotionEvent ACTION_DOWN,複数ACTION_MOVE,1 ACTION_UPトリガ
@Override
public boolean onSingleTapUp(MotionEvent e) {    
// TODO Auto-generated method stub 
   return false;    
}  

 
ユーザがタッチパネルを長押しし、複数のMotionEvent ACTION_DOWNトリガ
@Override  
public void onLongPress(MotionEvent e) {       
   // TODO Auto-generated method stub    
}

ユーザーがタッチパネルを押してドラッグし、1つのMotionEvent ACTION_DOWN,複数ACTION_MOVEトリガ
@Override  
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {      
    // TODO Auto-generated method stub    
    return false;       
}      
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {    
    // TODO Auto-generated method stub 
    return false;    
}

 
onFling()イベントの処理をしてみましょう.onFling()メソッドの各パラメータの意味をコメントに書きました.注意しなければならないのはFlingイベントの処理コードの中で、Flingを最初にトリガーするACTION_を除いてDOWNと最後のACTION_MOVEに含まれる座標などの情報に加え,X軸またはY軸におけるユーザの移動速度を条件としてもよい.例えば、以下のコードでは、ユーザが100画素以上移動し、X軸上の毎秒の移動速度が200画素より大きい場合に処理を行う.
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {   

//     :
// e1: 1 ACTION_DOWN MotionEvent 
// e2:    ACTION_MOVE MotionEvent 
// velocityX:X       ,  /  
// velocityY:Y       ,  /  
//      : 
// X        FLING_MIN_DISTANCE,       FLING_MIN_VELOCITY   /  
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE    
             && Math.abs(velocityX) > FLING_MIN_VELOCITY) {    

    // Fling left 
    Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();    
     } else
if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE    
             && Math.abs(velocityX) > FLING_MIN_VELOCITY) {    

     // Fling right 
     Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();    
}    

   return false;    
} 

 
問題は、この時にプログラムを実行しようとすると、私たちが望んでいる結果が得られないことに気づき、コードの実行を追跡するとonFling()イベントがキャプチャされていないことに気づきます.これはちょうど最初に私を困らせた問題で、これはいったいどうしてですか?ディスカッショングループのGesture detectionという投稿で答えを見つけました.つまり、onCreateでtvを必要とします.setOnTouchListener(this);その後、次のコードを追加します.tv.setLongClickable(true); このようにしてこそ、viewはTapと異なるhold(すなわちACTION_MOVE、または複数のACTION_DOWN)を処理することができ、layout定義におけるandroid:longClickableによっても同様に行うことができる.今回出会ったこの問題は前回MapViewでsetOnKeyListenerが出会った問題とよく似ていますが、実はSDKに対する理解が不十分で、一度覚えておけばいいのです.しかし、Googleはドキュメントの面で確かに強化する必要があります.少なくともOnGestureListenerでジェスチャーが正しく認識されることを保証するには、それらの条件を満たす必要があることを説明することができます.
変換元:http://dev.10086.cn/cmdn/wiki/index.php?edition-view-5880-1.html