2013-07-24 30 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; 
      } 
     }); 
相关问题