2013-01-23 25 views
7

onTouchジェスチャー onClickイベントを処理する必要があるビューがあります。これを達成するための適切な方法は何ですか?AndroidでonTouchとonClickイベントを受け取る

onTouchListeneronClickListenerが表示されています。ビューに触れるたびに、最初にonTouchイベントがトリガーされ、後でonClickがトリガーされます。しかし、onTouchイベントハンドラからは、trueまたはfalseのいずれかを返す必要があります。戻り値trueは、イベントが消費されていることを意味します。したがって、アンドロイドイベントシステムはそれ以上イベントを伝播しません。

したがって、onClickイベントが生成されることはありません、私は私のonTouchイベントハンドラでtrueを返すとき、少なくとも私のonClickリスナーがトリガされることはありません。一方、falseを返す場合は、リスナーがジェスチャーを認識するために必要なイベントを受信しないようにするため、オプションはありません。これを解決する通常の方法は何ですか?

+1

なぜあなたはonTouchとonClickが必要ですか?確かにonTouchで十分でしょう。 – JDx

+0

[GestureDetector](http://developer.android.com/reference/android/view/GestureDetector.html)はどうですか? – keyser

+0

@JDx「onTouchListener」からのクリックをどのように認識する必要がありますか?クリックは、少なくとも2つのタッチイベントのシーケンスであり、 'ACTION_DOWN'イベントは、後の' ACTION_UP'イベントと全く同じ位置(または少なくとも少なくとも同じビュー)で起動されます。確かに、これを実装することができ、他の解決策がない場合は私が行います。しかし、私の質問は確かに、このシナリオのための組み込みのソリューションがあるかどうかです? – theV0ID

答えて

5

onTouchListenerを使用する場合は、onClickListenerを使用する必要はありません。 onClickListenerでは、タッチイベントを取得し、イベントアクションを確認してクリックを検出することができます。もしあなたがonClickのときに仕事をしたいならば。アクションをフィルタリングすることでonTouchListenerでそれを行うことができます。

public boolean onTouch(View v, MotionEvent event) { 
if (event.getAction() == MotionEvent.ACTION_DOWN) { 
    //this is touch 

} 
if (event.getAction() == MotionEvent.ACTION_UP) { 
    //this is click 

} 
return false; 
} 
+0

'MotionEvent.ACTION_UP'ブロック内から' onClick'イベントを明示的に起動できますか? – theV0ID

+0

そして、私のビューが実際に 'ViewGroup'であり、その子ビューの中に' onClick'イベントを処理する必要があるものはどうでしょうか? – theV0ID

+0

V0ID、はいview.performClick()を呼び出すことで可能です。 –

0

は、私はあなたがonTouchlistenerを使用する場合は、ボタン、画像上のイベントをトリガするために、またはクリックのTextViewたいならば、ちょうどonClicklistener火災、onclicklistenerおよびその逆を使用する必要がいけない、JDXに同意します。ドラッグや回転などのアニメーションが必要な場合は、ontouchlistenerを使用してサーフェスの座標を取得します。

+0

既に指摘したように、私のビューが実際にViewGroupであり、その子ビューのいくつかがまだonClickイベントを処理する必要がある場合はどうなりますか? – theV0ID

+0

onclickとontouchリスナーが必要な状況があります。 ACTION_UP中にオンタッチからクリックイベントを生成することは同じではありません。 – AndroidDev

6

GestureDetectorでは、callOnClick()を直接呼び出すことができます。 View.callOnClick APIにはAPIレベル15が必要です。 試してみてください。

// Create a Gesturedetector 
GestureDetector mGestureDetector = new GestureDetector(context, new MyGestureDetector()); 

// Add a OnTouchListener into view 
m_myViewer.setOnTouchListener(new OnTouchListener() 
{ 

    @Override 
    public boolean onTouch(View v, MotionEvent event) 
    { 
     return mGestureDetector.onTouchEvent(event); 
    } 
}); 

private class MyGestureDetector extends GestureDetector.SimpleOnGestureListener 
{ 
    public boolean onSingleTapUp(MotionEvent e) { 
     // ---Call it directly--- 
     callOnClick(); 
     return false; 
    } 

    public void onLongPress(MotionEvent e) { 
    } 

    public boolean onDoubleTap(MotionEvent e) { 
     return false; 
    } 

    public boolean onDoubleTapEvent(MotionEvent e) { 
     return false; 
    } 

    public boolean onSingleTapConfirmed(MotionEvent e) { 
     return false; 

    } 

    public void onShowPress(MotionEvent e) { 
     LogUtil.d(TAG, "onShowPress"); 
    } 

    public boolean onDown(MotionEvent e) {    
     // Must return true to get matching events for this down event. 
     return true; 
    } 

    public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, float distanceY) { 
     return super.onScroll(e1, e2, distanceX, distanceY); 
    }   

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     // do something 
     return super.onFling(e1, e2, velocityX, velocityY); 
    } 
} 
+0

'callOnClick'メソッドはどこに定義されていますか?私はAPIで見つけることはできません、 'SimpleOnGestureListener'や' GestureDetector'のものでも見つかりません。 – theV0ID

+0

View.callOnClick APIにはAPIレベル15が必要です。http://developer.android.com/intl/zh-CN/reference/android/view/View.html#callOnClick()にアクセスできます。 SimpleOnGestureListenerはGestureDetector.OnGestureListenerから拡張されています。http://developer.android.com/intl/zh-CN/reference/android/view/GestureDetector.SimpleOnGestureListener.html – Autobots

0
isMove = false; 
case MotionEvent.ACTION_DOWN: 
//Your stuff 
isMove = false; 
case MotionEvent.ACTION_UP: 
if (!isMove || (Xdiff < 10 && Ydiff < 10) { 
view.performClick; //The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little 
even when you just click it 
} 
case MotionEvent.ACTION_MOVE: 
isMove = true; 

もう一つの方法は、スレッドを使用することです。それはAction_Down上にあり、カウンタをインクリメントするスレッドを開始します。 Action_UPの場合:スレッドを停止/中断します。それが2未満(例えばまたはしきい値アプリケーションごとなど)または!isMoveであれば、我々はフラグベースの実装を使用することができ、次にクリック機能を呼び出す

4
@Override 
    public boolean onTouch(View v, MotionEvent event) { 


     switch (event.getAction()) { 
      case MotionEvent.ACTION_MOVE: 
       layOutParams.x = initialX + (int) (event.getRawX() - initialTouchX); 
       layOutParams.y = initialY + (int) (event.getRawY() - initialTouchY); 

       break; 
      case MotionEvent.ACTION_DOWN: 
       initialX = layOutParams.x; 
       initialY = layOutParams.y; 
       initialTouchX = event.getRawX(); 
       initialTouchY = event.getRawY(); 
       if (initialTouchX == event.getRawX() && initialTouchY == event.getRawY()) { 
        return false;// to handle Click 
       } 
       break; 
      case MotionEvent.ACTION_UP: 
       if (initialTouchX == event.getRawX() && initialTouchY == event.getRawY()) { 
        return false;// to handle Click 
       } 
       break; 

     } 
     return true; 

    } 
}; 
0

にカウンタを探します。スワイプ/ドラッグでAction_Upで処理し、フラグをtrueにして返すことができます。 Action_Downでクリックまたは同じハンドルをタップし、フラグをfalseに設定して戻ります。

touchAndSwipe=false; 
     switch(e.getAction()){ 
     case MotionEvent.ACTION_MOVE:    
      break; 
     case MotionEvent.ACTION_DOWN:    
      x1 = e.getX(); 
      break; 
     case MotionEvent.ACTION_UP: 
      x2 = e.getX(); 
      float diff= x2-x1; 
       if(Math.abs(delta)>100){ 
       // Swipe 
       touchAndSwipe=true; 
       }else{ 
       touchAndSwipe=false; 
        }    
      break; 
     } 
     return touchAndSwipe; 
0

私は構築しているカスタムキーボードでOnClickとOnTouchを一緒に実装できました。作業するコードサンプルを含めていないので、このコードを見てコンテキストに合わせて修正することができます。

コードのサンプルを投稿すると、このサンプルを修正して、同じ結果を得ることができます。コンテキストはAndroid開発についてはすべてです。このコードスニペットを見て、役立つかどうかを確認してください。それ以外の場合は、自分のサンプルを投稿して、変更を加えて返信します。

 View DefaultphaseLay() { 

     LinearLayout mViewFirstPhase = (LinearLayout) getLayoutInflater().inflate(R.layout.layout_default_phase, parent); 

     ksOne_btn_LiLay = (LinearLayout) mViewFirstPhase.findViewById(R.id.ksOne_btn_LiLay); 
     ksOne_btn = (Button) mViewFirstPhase.findViewById(R.id.ksOne_btn); 
     ksOne_btn.setOnClickListener(mCorkyListener); 
     ksOne_btn.setFocusableInTouchMode(true); 
     ksOne_btn.setFocusable(true); 
     ksOne_btn.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 

       if (event.getAction() == MotionEvent.ACTION_DOWN) { 
        playClick(keyCode); 
        //v.startAnimation(animScale); 
        //key_sound.start(); 
        xkeys_lay.setVisibility(View.GONE); 
        numkeys_lay.setVisibility(View.GONE); 
        if (Constants.HapticFeedbackConstant) { 
         myVib.vibrate(Constants.vibration_duration); 
        } 
       } else if (event.getAction() == MotionEvent.ACTION_UP) { 
        ksOne_btn.setFocusable(false); //Check This Added This In Attempt to Kill Selector on Action_Up 
        //playClick(-100); 
        //key_sound.pause(); 
       } 
       return false; 
      } 
     }); 

     ChangeKeyBackgroundMehods.initChange_Key_Background(ksOne_btn_LiLay); 
     ChangeFontStyle.initChange_fontStyle(ksOne_btn, getApplicationContext()); 
     ChangeFont_size.initChange_fontSize(ksOne_btn, getApplicationContext()); 

これは、変更する必要がある他のコンテキストを送信または消費しようとするイベントの場合、アルファまたは数値出力のコンテキストで機能します。

+0

ここでは、switch/case vsを使用した別の例を示しますif/elseを下記に示しますが、アルファベット/数字で使用する場合は、押された状態とシフト状態を管理する必要があります。そうしないと、EditTextフィールドの出力に2文字の文字が表示されます。 –

関連する問題