2013-01-23 80 views
7

我認爲需要處理onTouch手勢 onClick事件。什麼是實現這一目標的正確途徑?使用Android接收onTouch和onClick事件

我有一個onTouchListener和一個onClickListener在視圖上設置。每當我觸摸視圖時,首先觸發onTouch事件,然後觸發onClick。但是,從onTouch事件處理程序,我必須返回truefalse。返回true意味着事件正在被消耗,所以android事件系統不會再傳播事件。

因此,從來沒有產生onClick事件,當我在onTouch事件處理程序返回true ATLEAST我onClick監聽器被觸發從來沒有。另一方面,返回false沒有選項,因爲這可以防止onTouch偵聽器接收任何進一步的事件來識別手勢。解決這個問題的常用方法是什麼?

+1

爲什麼你需要onTouch和onClick?當然只要onTouch就足夠了。 – JDx

+0

[GestureDetector](http://developer.android.com/reference/android/view/GestureDetector.html)如何? – keyser

+0

@JDx我該如何識別來自'onTouchListener'的點擊?點擊是至少兩個觸摸事件的序列,其中「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'-Event? – theV0ID

+0

theV0ID,是的,它可以通過調用view.performClick()。 –

0

我同意JDX,如果你使用onTouchlistener你不需要使用onclicklistener,反之亦然,如果要觸發按鈕,圖像的事件,或TextView的點擊,然後剛剛火onClicklistener。如果你想要一些動畫,如拖動和旋轉,然後使用ontouchlistener來獲得觸摸表面的座標

+0

正如已經指出的:如果我的觀點實際上是一個ViewGroup及其一些子視圖仍然需要處理onClick事件呢? – theV0ID

+0

在某些情況下,您需要使用onclick和ontouch偵聽器。在ACTION_UP期間從ontouch生成內部點擊事件不是一回事。 – 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中處理滑動/拖動操作,並使標誌爲真並返回相同的值。如果點擊或在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如果看到下面的內容,但如果使用alpha/numeric必須確保您管理按下的狀態和轉換狀態,否則您最終會在EditText字段的輸出中獲得雙字符。 –