android - 使用 GestureDetectorCompat 的奇怪行为

标签 android using

我有一个 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

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

最佳答案

已解决。

使用 LongPress 而不是双击并删除了 DoubleClick 处理程序。按要求工作。 MainActivity.doStuff 现在获得标签中带有“Long”或“Single”的调用。

我用的是缩放,单击步进缩放,长按恢复正常。

LongButton

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

}

关于android - 使用 GestureDetectorCompat 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57213060/

相关文章:

java - 测试 RxJava2 doOnComplete()

android - SSL 握手异常 : Connection closed by peer

Android 谷歌地图应用程序 - Mainactivity.java 错误

c# - LINQ 如何在 using 语句中延迟执行

c# - 在类级变量上使用 using 语句是不好的做法吗?

android - Dashclock 小部件扩展未更新

android - 并非自动授予 ACCOUNT 权限组中的所有权限

c++ - 别名表达式的最佳方法

c++ - `using` 用户定义文字运算符的声明

c# - 在 C# 中对同一作用域使用多个 using 语句时,Dispose() 方法的调用顺序是否有保证?