首页 > 解决方案 > 使用 GestureDetectorCompat 的奇怪行为

问题描述

我有一个 DoubleTapButton 类有一个奇怪的问题。

该按钮在 main_activity.xml 文件中定义,包括 onClick、MainActivity.DoStuff。

问题是当单击按钮时,按钮在 GestureDetector.OnDoubleTapListener 知道单击或双击之前调用 MainActivity.DoStuff。

我的 DoubleTapButton 使用 setTag() 设置按钮标签,doStuff 方法读取标签。标签设置正确,但直到调用 doStuff 方法之后。为时已晚,无法使用。

我想我在这里遗漏了一步,但我这几天一直在扰乱这段代码,似乎无法让它正常工作。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<kenz.a.testbutton.DoubleTapButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Do Stuff"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:onClick="doStuff"/>

类 DoubleTapButton

package kenz.a.testbutton;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import androidx.appcompat.widget.AppCompatButton;
import androidx.core.view.GestureDetectorCompat;

public class DoubleTapButton
   extends AppCompatButton
   implements GestureDetector.OnGestureListener,
              GestureDetector.OnDoubleTapListener {

private String TAG = "KENZ DoubleTapButton";
private GestureDetectorCompat myDetector;

public DoubleTapButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    myDetector = new GestureDetectorCompat(context,this);
    setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return myDetector.onTouchEvent(event);
        }
    });
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
    Log.d(TAG, "onSingleTapConfirmed: Setting View Tag("+getId()+") Single");
    setTag(getId(),"Single");
    return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
    Log.d(TAG, "onDoubleTap: Setting View Tag("+getId()+") Double");
    setTag(getId(),"Double");
    return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
    return false;
}
@Override
public boolean onDown(MotionEvent e) {
    return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
    return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    return false;
 }
}

类 MainActivity

package kenz.a.testbutton;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

 import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
String TAG = "Kenz MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}
public void doStuff(View view) {
    String s;
    if(view.getTag(view.getId())==null)s="Null";
    else s = view.getTag(view.getId()).toString();
    Log.d(TAG, "doStuff: "+view.getTag(view.getId()));
    Toast.makeText(this,s,Toast.LENGTH_SHORT).show();
 }
 }

LogCat 输出

07-25 23:16:15.154 26047-26047/kenz.a.testbutton D/Kenz MainActivity: doStuff: null
07-25 23:16:15.334 26047-26047/kenz.a.testbutton D/KENZ DoubleTapButton: onSingleTapConfirmed: Setting View Tag(-1) Single
07-25 23:16:21.450 26047-26047/kenz.a.testbutton D/Kenz MainActivity: doStuff: Single
07-25 23:16:21.580 26047-26047/kenz.a.testbutton D/KENZ DoubleTapButton: onDoubleTap: Setting View Tag(-1) Double
07-25 23:16:25.074 26047-26047/kenz.a.testbutton D/Kenz MainActivity: doStuff: Double
07-25 23:16:25.204 26047-26047/kenz.a.testbutton D/KENZ DoubleTapButton: onDoubleTap: Setting View Tag(-1) Double
07-25 23:16:27.436 26047-26047/kenz.a.testbutton D/Kenz MainActivity: doStuff: Double
07-25 23:16:27.646 26047-26047/kenz.a.testbutton D/KENZ DoubleTapButton: onSingleTapConfirmed: Setting View Tag(-1) Single

似乎 onClick 在 GestureDetector.OnDoubleTapListener 知道单击或双击之前调用了 MainActivity.doStuff(View view) 。我想我在这里遗漏了一步,但我这几天一直在扰乱这段代码,似乎无法让它正常工作。

标签: androidusing

解决方案


解决了。

使用 LongPress 而不是双击并删除了 DoubleClick 处理程序。根据需要工作。MainActivity.doStuff 现在在标签中使用“Long”或“Single”来获取调用。

我用它来缩放,单击步进缩放,长恢复正常。

长按钮

enter code here
package kenz.a.testbutton;

    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.GestureDetector;
    import android.view.MotionEvent;
    import android.view.View;

    import androidx.appcompat.widget.AppCompatButton;
    import androidx.core.view.GestureDetectorCompat;

public class LongButton
    extends AppCompatButton
    implements GestureDetector.OnGestureListener {

private String TAG = "KENZ LongButton";
private GestureDetectorCompat mDetector;
Long dtime = System.currentTimeMillis();

public LongButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    mDetector = new GestureDetectorCompat(context,this);
    setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return mDetector.onTouchEvent(event);
        }
    });
}
@Override
public boolean onDown(MotionEvent e) {
    return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
    Long curTime = System.currentTimeMillis();
    if(curTime-dtime < 200) setTag(getId(),"Double Click");
    else {
        dtime = System.currentTimeMillis();
        setTag(getId(), "Single Click");
    }
    return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    return false;
}
@Override
public void onLongPress(MotionEvent e) {
    Log.d(TAG, "onLongPress: Setting View Tag("+getId()+") Long");
    setTag(getId(),"Long Click");
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    return false;
}

}

推荐阅读