Android中按钮的单击和双击

8

在我的应用程序中,我有一个按钮。单击和双击按钮将执行不同的操作。我该怎么做呢?谢谢。


1
只需设置一个名为 count 的全局变量,并在单击事件中对其进行递增。当 count=2 时,执行双击操作并将其重置为 count=0。 - Hemantvc
12个回答

11

很简单,只需要覆盖重写。

OnClickListener的onClick方法

public abstract class DoubleClickListener implements View.OnClickListener {
private static final long DEFAULT_QUALIFICATION_SPAN = 200;
private boolean isSingleEvent;
private long doubleClickQualificationSpanInMillis;
private long timestampLastClick;
private Handler handler;
private Runnable runnable;

public DoubleClickListener() {
    doubleClickQualificationSpanInMillis = DEFAULT_QUALIFICATION_SPAN;
    timestampLastClick = 0;
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            if (isSingleEvent) {
                onSingleClick();
            }
        }
    };
}

@Override
public void onClick(View v) {
    if((SystemClock.elapsedRealtime() - timestampLastClick) < doubleClickQualificationSpanInMillis) {
        isSingleEvent = false;
        handler.removeCallbacks(runnable);
        onDoubleClick();
        return;
    }

    isSingleEvent = true;
    handler.postDelayed(runnable, DEFAULT_QUALIFICATION_SPAN);
    timestampLastClick = SystemClock.elapsedRealtime();
}

public abstract void onDoubleClick();
public abstract void onSingleClick();
}

使用方法

 button.setOnClickListener(new DoubleClickListener() {
        @Override
        public void onDoubleClick() {
            Log.i("onClick", "double");
        }

        @Override
        public void onSingleClick() {
            Log.i("onClick", "single");
        }
    });

应该被接受为答案,因为它完全按预期工作。 - Zash__
我能找到的最佳答案。如果有人发现有用,我发布了Kotlin翻译。Steve S. - steven smith

9
您可能需要创建一个延迟变量,以区分单击和双击。
请看以下代码:
private static final long DOUBLE_PRESS_INTERVAL = 250; // in millis
private long lastPressTime;

private boolean mHasDoubleClicked = false;

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {    

        // Get current time in nano seconds.
        long pressTime = System.currentTimeMillis();


        // If double click...
        if (pressTime - lastPressTime <= DOUBLE_PRESS_INTERVAL) {
            Toast.makeText(getApplicationContext(), "Double Click Event", Toast.LENGTH_SHORT).show();
            mHasDoubleClicked = true;
        }
        else {     // If not double click....
            mHasDoubleClicked = false;
            Handler myHandler = new Handler() {
                 public void handleMessage(Message m) {
                      if (!mHasDoubleClicked) {
                            Toast.makeText(getApplicationContext(), "Single Click Event", Toast.LENGTH_SHORT).show();
                      }
                 }
            };
            Message m = new Message();
            myHandler.sendMessageDelayed(m,DOUBLE_PRESS_INTERVAL);
        }
        // record the last time the menu button was pressed.
        lastPressTime = pressTime;      
        return true;
    }

嗨,感谢您的回复。实际上,我想知道如何将它应用于按钮上,因为我是Android的新手。 - andDev
@ Rynold,我使用了你的代码,但是当我双击时,单击事件中的代码也会执行。你能帮我解决一下吗? - Manikandan
为什么要使用处理程序类 @Raynold - Xplosive
我认为你应该使用ViewConfiguration.getDoubleTapTimeout()来作为DOUBLE_PRESS_INTERVAL,以保持与其他Android双击操作的一致性。 - Almighty

6

您可能需要考虑不使用DoubleTap。这不是Android的正常行为。

当我第一次在Android上编程时,我经常遇到一些非常“困难”的事情。随着时间的推移,我发现其中许多都很困难,因为它们是一个相当糟糕的想法。

如果您正在移植iOS应用程序或模拟iOS应用程序的行为,则可能需要将UI转换为Android样式行为并使用longPress或其他“androidy”手势。

这里有一个类似的问题和答案:

Android:如何检测double-tap?


4

您需要实现 GestureDetector 并将代码放在 单击/双击 中。

TestActivity.java

iv.setOnClickListener(new OnClickListener() {           
                @Override
                public void onClick(View v) {
                    //putyour first activity call.
                }
    }

iv.setOnTouchListener(new OnTouchListener() {
             GestureDetector gestureDetector = new GestureDetector(context, new MyGestureDetector(context));
         @Override
         public boolean onTouch(View v, MotionEvent event) {
                return gestureDetector.onTouchEvent(event);
         }
});

现在您需要创建GestureDetector.java类。
public class MyGestureDetector extends SimpleOnGestureListener {
    public Context context;
    public String phno;

    public MyGestureDetector(Context con) {
        this.context=con;       
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return super.onDown(e);
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        System.out.println("in Double tap");

        return true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        System.out.println("in single tap up");
            //put your second activity.
        return super.onSingleTapUp(e);
    }   
}

嗨,感谢您的回复。通过这段代码,当我尝试执行双触操作时,它也会执行单触操作。如何在双触时停止单触操作? - andDev
@andDev 你需要在单击/双击中要求相同的函数调用,那有什么问题吗? - Harshid
实际上我需要为单触和双触分别使用两个活动。 - andDev
public boolean onDoubleTap(MotionEvent e) { //System.out.println("in Double tap"); flag = 2; Intent intent=new Intent(getApplicationContext(),Click2.class); startActivity(intent); return true; } @Override public boolean onSingleTapUp(MotionEvent e) { //System.out.println("in single tap up"); flag=1;
Intent intent=new Intent(getApplicationContext(),Click1.class); startActivity(intent); return super.onSingleTapUp(e); }
- andDev
同一个问题。两个活动同时开始。 - andDev

3

3

虽然现在有点晚了,但是任何人看到这一点都可以理解。

int number_of_clicks = 0;
boolean thread_started = false;
final int DELAY_BETWEEN_CLICKS_IN_MILLISECONDS = 250;

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ++number_of_clicks;
        if(!thread_started){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread_started = true;
                    try {
                        Thread.sleep(DELAY_BETWEEN_CLICKS_IN_MILLISECONDS);
                        if(number_of_clicks == 1){
                            client.send(AppHelper.FORMAT_LEFT_CLICK);
                        } else if(number_of_clicks == 2){
                            client.send(AppHelper.FORMAT_DOUBLE_CLICK);
                        }
                        number_of_clicks = 0;
                        thread_started = false;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
});

解释:


在按钮单击之前,number_of_click被初始化为0。 thread_started是一个标志,检测线程是否之前已经启动。 现在,在按钮单击时,通过增量运算符增加按钮单击次数。 检查线程以前是否启动过,如果没有,则启动线程。 在线程中,使用number_of_clicks和线程将等待下一个毫秒,然后经过您的逻辑。 所以,现在您可以应用任意多次点击。


2
这是@saksham在Kotlin中的答案。
abstract class DoubleClickListener : View.OnClickListener {
    private val DEFAULT_QUALIFICATION_SPAN = 200L
    private var isSingleEvent = false
    private val doubleClickQualificationSpanInMillis =
        DEFAULT_QUALIFICATION_SPAN
    private var timestampLastClick = 0L
    private val handler = Handler(Looper.getMainLooper())
    private val runnable: () -> Unit = {
        if (isSingleEvent) {
            onSingleClick()
        }
    }
    override fun onClick(v: View) {
        if (SystemClock.elapsedRealtime() - timestampLastClick < doubleClickQualificationSpanInMillis) {
            isSingleEvent = false
            handler.removeCallbacks(runnable)
            onDoubleClick()
            return
        }
        isSingleEvent = true
        handler.postDelayed(runnable, DEFAULT_QUALIFICATION_SPAN)
        timestampLastClick = SystemClock.elapsedRealtime()
    }

    abstract fun onDoubleClick()
    abstract fun onSingleClick()
}

1
通过继承View.OnClickListener并检查点击时间来区分单击或双击,解决此问题,这也解决了快速点击的问题。此解决方案将带来较小的代码更改,只需替换View.OnClickLister。您还可以覆盖getGap()以重新定义两次点击之间的时间。
import android.os.SystemClock;
import android.view.View;

/*****
 * Implement to fix the double click problem.
 * Avoid the fast double click for button and images.
 */
public abstract class OnSingleClickListener implements View.OnClickListener {
    private long prevClickTime =0;

    @Override
    public void onClick(View v) {
        _onClick(v);
    }

    private synchronized void _onClick(View v){
        long current = SystemClock.elapsedRealtime();
        if(current-prevClickTime> getGap()){
            onSingleClick(v);
            prevClickTime = SystemClock.elapsedRealtime();
        }else {
            onDoubleClick(v);
            prevClickTime = 0;
        }
    }

    public abstract void onSingleClick(View v);
    public abstract void onDoubleClick(View v);

    /********
     *
     * @return The time in ms between two clicks.
     */
    public long getGap(){
        return 500L; //500ms
    }
}

1

安卓系统中的双击和单击

适用于几乎所有版本的解决方案

检测在您想要定义的标准时间内事件类型。它可以加速地连续地检测事件,例如在一定时间内通过视频

//general definition
private CountDownTimer countDownTimer;
private int click_duble = 1;

button.setOnClickListener(view -> {

    if (countDownTimer == null) {
        float Second= (float) 0.25; //Detecting the type of event within a quarter of a second
        countDownTimer= new CountDownTimer((long) (Second * 1000), 50) {
            @Override public void onTick(long l){}
            @Override
            public void onFinish() {
                if (click_duble >= 2) {
                    Toast.makeText(player_fb.this, "Double", Toast.LENGTH_SHORT).show();

                } else {
                    Toast.makeText(player_fb.this, "Single", Toast.LENGTH_SHORT).show();
                }
                click_duble = 1;
                countDownTimer = null;
            }};countDownTimer.start();
    }else
        click_duble += 1;
});

0

对于多次点击,之前的解决方案无法工作,我测试过但失败了。

因此,我建议使用RxBinding和ProgressDialog。

当点击按钮时,ProgressDialog会显示设置,它不能被取消,修复它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接