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
在滚动视图中。我需要能够水平和垂直滚动。为了实现这一点,必须在触摸myViewPager
时禁用垂直滚动(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;
}
}
}