2013-07-24 27 views
16

我在ScrollView內有ViewPager。我需要能夠水平滾動以及垂直滾動。爲了達到這個目的,必須在我的ViewPager被觸摸時禁用垂直滾動(v.getParent().requestDisallowInterceptTouchEvent(true);),以便它可以水平滾動。如何檢測onTouch偵聽器中的點擊?

但同時我需要能夠點擊viewPager以全屏模式打開它。

問題是onClick在onClick之前被調用,而我的OnClick從未被調用過。

我該如何在觸摸onClick時實現這兩個操作?

viewPager.setOnTouchListener(new OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     System.out.println("TOUCHED "); 
     if(event.getAction() == MotionEvent.???){ 
      //open fullscreen activity 
     } 
     v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed 
     return false; 
    } 
}); 

viewPager.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     System.out.println("CLICKED "); 
     Intent fullPhotoIntent = new Intent(context, FullPhotoActivity.class); 
     fullPhotoIntent.putStringArrayListExtra("imageUrls", imageUrls); 
     startActivity(fullPhotoIntent); 
    } 
}); 
+0

你試過從onTouch返回true? – Desert

回答

44

Masoud Dadashi的回答幫助我弄明白了。

這裏是它最終的樣子。

viewPager.setOnTouchListener(new OnTouchListener() { 
    private int CLICK_ACTION_THRESHOLD = 200; 
    private float startX; 
    private float startY; 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      startX = event.getX(); 
      startY = event.getY(); 
      break; 
     case MotionEvent.ACTION_UP: 
      float endX = event.getX(); 
      float endY = event.getY(); 
      if (isAClick(startX, endX, startY, endY)) { 
       launchFullPhotoActivity(imageUrls);// WE HAVE A CLICK!! 
      } 
      break; 
     } 
     v.getParent().requestDisallowInterceptTouchEvent(true); //specific to my project 
     return false; //specific to my project 
    } 

    private boolean isAClick(float startX, float endX, float startY, float endY) { 
     float differenceX = Math.abs(startX - endX); 
     float differenceY = Math.abs(startY - endY); 
     return !(differenceX > CLICK_ACTION_THRESHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHOLD); 
    } 
} 
+0

它的工作原理,但這停止了回收商視圖的滾動。 – mark922

+0

@ mark922我不確定關於recyler視圖,當我使用此代碼時,我在ListView上使用它 – code511788465541441

+0

爲什麼CLICK_ACTION_THRESHOLD是200像素? – Lester

0

我覺得你的問題來自於行:

v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed 

看看到documentation。 您是否嘗試刪除該行?什麼是不刪除這條線的要求?

根據documentation,考慮到如果從onTouchListener返回true,則該事件將被消耗,並且如果返回false,則會被傳播,因此您可以使用它傳播該事件。

System.out.println("CLICKED "); 

到:

此外,你應該從改變你的代碼

Log.d("MyApp", "CLICKED "); 

要在logcat中獲得正確的輸出。

0

我相信你會阻止你的視圖以這種方式接收觸摸事件,因爲你的TouchListener攔截它。 您可以

  • 調度通過調用v.onTouchEvent(event)
  • 覆蓋您ToucheListener內的事件,而不是ViewPager.onTouchEvent(MotionEvent)不攔截事件

此外,返回true意味着你沒有消耗該事件,並且您對以下事件不感興趣,並且因此在手勢完成之前您不會收到以下事件(即手指再次啓動)。

9

開發兩者都是錯誤的想法。當用戶可以通過觸摸屏幕來做不同的事情時,理解用戶的目的有點漂亮,你需要爲它開發一段代碼。

兩個解決方案:

1-(對更好的主意)在onTouch活動檢查是否有運動。

ACTION_UP 
ACTION_DOWN 
ACTION_MOVE 

做這樣的

if(event.getAction() != MotionEvent.ACTION_MOVE) 

你甚至可以檢查在屏幕上用戶手指的移動距離,以確保運動:如果使用任何移動可以通過檢查做發生而不是點擊時的意外移動。像這樣做:

switch(event.getAction()) 
{ 
    case MotionEvent.ACTION_DOWN: 
       if(isDown == false) 
       { 
        startX = event.getX(); 
        startY = event.getY(); 
        isDown = true; 
       } 
       Break; 
     case MotionEvent.ACTION_UP 
       { 
        endX = event.getX(); 
        endY = event.getY(); 
        break; 
      } 
} 

認爲它是一個點擊,如果沒有發生上述事情,並做你想做點擊。 2)如果你的用戶界面(UI)流氓,創建一個按鈕或圖像按鈕或任何其他的全屏幕,併爲它設置一個onClick。

祝你好運

+0

所以如果'!isDown &&!isUp'意味着它是一個點擊?這是爲什麼?。我剛剛嘗試過,當我點擊時它並沒有工作。 – code511788465541441

+0

isDown被刪除。嘗試使用ACTION_DOWN和ACTION_UP來代替,因爲我已經在上面提到 –

+4

appologies,但它不是關於聲譽。我沒有接受我自己的答案而獲得任何聲望。我已經提高了你的答案,所以你會得到一些聲譽。我認爲這對於下一個看這個問題的人來說能夠得到完整的答案會更有幫助。如果你願意,你可以用我的答案更新你的答案,我將刪除我的並接受你的 – code511788465541441

4

您可能需要區分用戶單擊和長按。否則,你會發現兩者都是一樣的。我做到了這一點:

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    switch (event.getAction()) { 
    case MotionEvent.ACTION_DOWN: 
     startX = event.getX(); 
     startY = event.getY(); 

     bClick = true; 
     tmrClick = new Timer(); 
     tmrClick.schedule(new TimerTask() { 
      public void run() { 
       if (bClick == true) { 
        bClick = false; 
        Log.d(LOG_TAG, "Hey, a long press event!"); 
        //Handle the longpress event. 
       } 
      } 
     }, 500); //500ms is the standard longpress response time. Adjust as you see fit. 

     return true; 
    case MotionEvent.ACTION_UP: 
     endX = event.getX(); 
     endY = event.getY(); 

     diffX = Math.abs(startX - endX); 
     diffY = Math.abs(startY - endY); 

     if (diffX <= 5 && diffY <= 5 && bClick == true) { 
      Log.d(LOG_TAG, "A click event!"); 
      bClick = false; 
     } 
     return true; 
    default: 
     return false; 
    } 
} 
+0

awsome dude ..很有用的答案... –

9

我做了一些非常簡單的事情,記錄了用戶觸摸屏幕的時間。 。

private long lastTouchDown; 
private static int CLICK_ACTION_THRESHHOLD = 200; 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      lastTouchDown = System.currentTimeMillis(); 
      break; 
     case MotionEvent.ACTION_UP: 
      if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD) { 
       Log.w("App", "You clicked!"); 
      } 
      break; 
    } 
    return true; 
} 

另外值得一提的是,GestureDetector有這個建於只看onSingleTapUp

+4

你可以不用私有變量來做到這一點。** duration = event.getEventTime() - event.getDownTime()** –

1

我認爲聯合解決方案的時間/位置應該會更好:

private float initialTouchX; 
private float initialTouchY; 
private long lastTouchDown; 
private static int CLICK_ACTION_THRESHHOLD = 100; 
@Override 
      public boolean onTouch(View v, MotionEvent event) { 
       switch (event.getAction()) { 
        case MotionEvent.ACTION_DOWN: 

         lastTouchDown = System.currentTimeMillis(); 

         //get the touch location 
         initialTouchX = event.getRawX(); 
         initialTouchY = event.getRawY(); 
         return true; 
        case MotionEvent.ACTION_UP: 
         int Xdiff = (int) (event.getRawX() - initialTouchX); 
         int Ydiff = (int) (event.getRawY() - initialTouchY); 

         if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD && (Xdiff < 10 && Ydiff < 10)) { 
          //clicked!!! 
         } 
         return true; 
       } 
       return false; 
      } 
     }); 
相關問題