Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在onTouch侦听器中检测单击?_Java_Android_Android Viewpager - Fatal编程技术网

Java 如何在onTouch侦听器中检测单击?

Java 如何在onTouch侦听器中检测单击?,java,android,android-viewpager,Java,Android,Android Viewpager,我有一个ViewPager在滚动视图中。我需要能够水平和垂直滚动。为了实现这一点,必须在触摸myViewPager时禁用垂直滚动(v.getParent().RequestDisallowWinterCeptTouchEvent(true);),以便可以水平滚动 但同时,我需要能够单击viewPager以全屏模式打开它 问题是onTouch在onClick之前被调用,而my onClick从未被调用。 如何在触摸屏和onClick上实现这两种功能? viewPager.setOnTouchLis

我有一个
ViewPager
滚动视图中。我需要能够水平和垂直滚动。为了实现这一点,必须在触摸my
ViewPager
时禁用垂直滚动(
v.getParent().RequestDisallowWinterCeptTouchEvent(true);
),以便可以水平滚动

但同时,我需要能够单击viewPager以全屏模式打开它

问题是onTouch在onClick之前被调用,而my 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);
    }
});

我认为你的问题来自以下方面:

v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed
请看下面的图片。 你试过把电话线拔下来吗?不删除此行的要求是什么?

根据,请考虑,如果您从onTouchListener返回true,则事件将被消费,如果您返回false,则事件将被传播,因此您可以使用它来传播事件

此外,您还应该从以下位置更改代码:

 System.out.println("CLICKED ");
致:


要在logcat中获得正确的输出。

我认为您正在阻止视图以这种方式接收触摸事件,因为您的TouchListener会拦截它。 你也可以

  • 通过调用
    v.onTouchEvent(event)
  • 改为覆盖ViewPager.onTouchEvent(MotionEvent)
以不截获事件

此外,返回
true
表示您没有使用事件,并且您没有参与后续事件,因此在手势完成之前(即,手指再次竖起)您不会接收后续事件。

发展这两种情况是错误的想法。当用户可以通过触摸屏幕来做不同的事情时,理解用户的目的有点巧妙,您需要为此开发一段代码

两种解决方案:

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) 如果你的用户界面有问题,创建一个按钮或图像按钮或任何全屏显示的东西,并设置一个onClick


祝你好运

马苏德·达达西的回答帮助我找到了答案

下面是它最后的样子

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);
    } 
}

您可能需要区分用户单击和长时间单击。否则,您会将两者检测为同一事物。我这样做是为了让这成为可能:

@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;
    }
}
@覆盖
公共布尔onTouch(视图v,运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
startX=event.getX();
startY=event.getY();
bClick=true;
tmrClick=新定时器();
tmrClick.schedule(新TimerTask(){
公开募捐{
if(bClick==true){
bClick=false;
Log.d(Log_标签,“嘿,一个长新闻事件!”);
//处理longpress事件。
}
}
},500);//500ms是标准的longpress响应时间。根据需要进行调整。
返回true;
case MotionEvent.ACTION\u UP:
endX=event.getX();
endY=event.getY();
diffX=Math.abs(startX-endX);
diffY=Math.abs(startY-endY);

如果(diffX我通过检查用户触摸屏幕的时间做了一些非常简单的事情

private static int CLICK_THRESHOLD = 100;

@Override
public boolean onTouch(View v, MotionEvent event) {
    long duration = event.getEventTime() - event.getDownTime();

    if (event.getAction() == MotionEvent.ACTION_UP && duration < CLICK_THRESHOLD) {
        Log.w("bla", "you clicked!");
    }

    return false;
}
private static int CLICK_THRESHOLD=100;
@凌驾
公共布尔onTouch(视图v,运动事件){
长持续时间=event.getEventTime()-event.getDownTime();
if(event.getAction()==MotionEvent.ACTION\u UP&&duration

同样值得注意的是,它具有类似于此的内置功能。请查看onSingleTapUp,您可以使用OnTouchClickListener

用法:

view.setOnTouchListener(新建OnTouchClickListener(新建OnTouchClickListener.OnClickListener()){
@凌驾
公共void onClick(视图v){
//执行onClick
}

},5));
我认为组合解决方案时间/位置应该更好:

 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;
            }
        });
private float initialTouchX;
私家侦探敏感;
私人长距离触地;
私有静态int单击\操作\阈值=100;
@凌驾
公共布尔onTouch(视图v,运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
lastTouchDown=System.currentTimeMillis();
//获取触摸位置
initialTouchX=event.getRawX();
initialTouchY=event.getRawY();
返回true;
case MotionEvent.ACTION\u UP:
int Xdiff=(int)(event.getRawX()-initialTouchX);
int-Ydiff=(int)(event.getRawY()-initialTouchY);
if(System.currentTimeMillis()-lastTouchDown<单击\u操作\u阈值&&(Xdiff<10&&Ydiff<10)){
//点击!!!
}
返回true;
}
返回false;
}
});

上面的答案大部分都会记住时间。但是,
MotionEvent
已经介绍过了。这里有一个开销较小的解决方案。它是用
kotlin
编写的,但应该仍然可以理解:

private const val ClickThreshold = 100

override fun onTouch(v: View, event: MotionEvent): Boolean {
    if(event.action == MotionEvent.ACTION_UP 
      && event.eventTime - event.downTime < ClickThreshold) {
        v.performClick()
        return true // If you don't want to do any more actions
    }

    // do something in case its not a click

    return true // or false, whatever you need here
}
private const val ClickThreshold=100
override fun onTouch(v:View,event:MotionEvent):布尔值{
如果(event.acti)
private const val ClickThreshold = 100

override fun onTouch(v: View, event: MotionEvent): Boolean {
    if(event.action == MotionEvent.ACTION_UP 
      && event.eventTime - event.downTime < ClickThreshold) {
        v.performClick()
        return true // If you don't want to do any more actions
    }

    // do something in case its not a click

    return true // or false, whatever you need here
}
public class CustomView extends View {

    private GestureDetectorCompat mDetector;

    public CustomView(Context context) {
        super(context);
        mDetector = new GestureDetectorCompat(context, new MyGestureListener());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        return this.mDetector.onTouchEvent(event);
    }

    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onDown(MotionEvent e) {return true;}

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            //...... click detected !
            return false;
        }
    }
}