버튼을 두 번 클릭하는 것을 방지하는 Android


177

Android에서 버튼을 두 번 클릭하는 것을 방지하는 가장 좋은 방법은 무엇입니까?


3
단지 그것을 충분히 가능한 qezt의 솔루션을 참조하십시오
나디 Ryabkin

3
이 페이지를 방문하는 사람들이 setEnabled (false) 사용의 단점을 알 수 있도록 qezt의 솔루션이 승인 되었어야합니다.
LoveForDroid

당신은 마지막 클릭 - 시간의 솔루션을 사용하여, 내 라이브러리를 시도 할 수 있습니다 : github.com/RexLKW/SClick
렉스 램

1
@Androider 최선의 답변을 변경하십시오
Amir133

답변:


87

setEnabled(false)사용자가 다시 클릭하기에 안전 할 때까지 버튼을 비활성화 하십시오.


47
setEnabled (false)가 "빠른"작동하지 않는 것 같습니다. 버튼에 대해 View.OnClickListener.onClick (view)을 설정했습니다. onClick ()에서 가장 먼저하는 일은 로그 문을 작성하는 것이고 두 번째 문은 button.setEnabled (false)입니다. 에뮬레이터에서 빠르게 두 번 클릭하면 로그 문이 두 번 나타납니다! 그 직후에 setClickable (false)을 추가하더라도 로그 문은 두 번 나타납니다.
QQQuestions

흠, 아마도 onClick ()의 ​​끝에서 setEnabled (true)까지의 코드가 너무 빨리 실행되어 이미 다시 활성화되었습니다 ...
QQQuestions

91
나는 비슷한 문제가 있었다. 도움이되는 한 신사에 따르면, Android는 실제로 클릭을 대기 시키므로 onClick () 코드의 실행 속도와 속도는 중요하지 않습니다. 버튼을 얼마나 빨리 클릭하는지. 즉. 이미 버튼을 사용 중지했을 수도 있지만 클릭 대기열에 이미 2 ~ 3 번의 클릭이 채워져 있으며 버튼을 사용 중지해도 대기열에있는 클릭이 게재되지 않습니다. (아마도 그래야합니까?)
Nick

3
당신이 '누군가'를 볼 때 그 드문 순간은 정확한 답변을 제공하지만 질문에 대한 답변을 절대적으로 언급하지 않습니다. : : P
Rahul

이것이 항상 올바른 해결책은 아닙니다. onClick 작동이 비싸면 버튼이 충분히 빨리 비활성화되지 않습니다. 완벽한 솔루션 IMHO는 마지막 클릭 시간을 사용하는 한편, 작업이 오래 지속될 것으로 예상되는 경우 (예 : 로그인) 버튼을 다시 사용하지 않도록 버튼을 비활성화합니다.
Sarang

368

클릭 할 때 마지막 클릭 시간을 저장하면이 문제를 방지 할 수 있습니다.

private long mLastClickTime = 0;

...

// inside onCreate or so:

findViewById(R.id.button).setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // mis-clicking prevention, using threshold of 1000 ms
        if (SystemClock.elapsedRealtime() - mLastClickTime < 1000){
            return;
        }
        mLastClickTime = SystemClock.elapsedRealtime();

        // do your magic here
    }
}

21
이것이 실제로 더블 클릭을 방지하는 유일한 솔루션입니다. 이 방법은 꽤 어색하기 때문에 다른 모든 것을 시도하는 데 한 시간을 보냈지 만 아무도이 방법을 제외하고 빠른 두 번 누르기를 막을 수는 없었습니다. 구글 :이 문제를 해결하시기 바랍니다 :)
ashishduh

6
이 솔루션은 제대로 작동합니다.이 솔루션은 화면에 여러 버튼이 있고 한 번에 하나의 버튼 만 클릭하려는 경우에도 작동합니다.
void

12
충분히 빠르게 두 번 클릭해도 더블 클릭을 완전히 막을 수는 없습니다.
Loc

4
우수 답변, 그것은 상단에 있어야합니다
나디 Ryabkin

3
이 솔루션은 정답이어야합니다 ... setEnabled (false) 충분하지 않습니다.
heloisasim

55

내 해결책은

package com.shuai.view;

import android.os.SystemClock;
import android.view.View;

/**
 * 处理快速在某个控件上双击2次(或多次)会导致onClick被触发2次(或多次)的问题
 * 通过判断2次click事件的时间间隔进行过滤
 * 
 * 子类通过实现{@link #onSingleClick}响应click事件
 */
public abstract class OnSingleClickListener implements View.OnClickListener {
    /**
     * 最短click事件的时间间隔
     */
    private static final long MIN_CLICK_INTERVAL=600;
    /**
     * 上次click的时间
     */
    private long mLastClickTime;

    /**
     * click响应函数
     * @param v The view that was clicked.
     */
    public abstract void onSingleClick(View v);

    @Override
    public final void onClick(View v) {
        long currentClickTime=SystemClock.uptimeMillis();
        long elapsedTime=currentClickTime-mLastClickTime;
        //有可能2次连击,也有可能3连击,保证mLastClickTime记录的总是上次click的时间
        mLastClickTime=currentClickTime;

        if(elapsedTime<=MIN_CLICK_INTERVAL)
            return;

        onSingleClick(v);        
    }

}

사용법은 OnClickListener와 유사하지만 대신 onSingleClick ()을 재정의하십시오.

mTextView.setOnClickListener(new OnSingleClickListener() {
            @Override
            public void onSingleClick(View v) {
                if (DEBUG)
                    Log.i("TAG", "onclick!");
            }
     };

1
더블 터치를 자동으로 방지하는 쉽고 완벽합니다.
Benjamin Piette

1
충분히 빠르게 두 번 클릭해도 더블 클릭을 완전히 막을 수는 없습니다.
Loc

1
훌륭한 솔루션. 방금 MIN_CLICK_INTERVAL = 1000을 변경했습니다.
Nizam

5
0.5 초마다 정확하게 버튼을 클릭하면 매번 클릭 할 때 mLastClickTime이 업데이트되므로 후속 클릭이 발생하지 않습니다. 간격을 확인한 후 mLastClickTime을 할당하는 것이 좋습니다.
k2col

mLastClickTime = 현재 클릭 시간; if (elapsedTime <= MIN_CLICK_INTERVAL) 반환 후 배치해야합니다.
Loyea

41

버튼을 비활성화하기 전에 클릭 이벤트가 대기 될 수 있으므로 onClick ()에서 계산 집약적 인 작업을 수행하는 경우 버튼을 비활성화하거나 클릭 할 수없는 설정으로 충분하지 않습니다. 대신 클릭 할 수있는 OnClickListener를 구현하는 추상 기본 클래스를 작성했습니다. 대기 된 클릭을 무시 하여이 문제를 해결합니다.

/** 
 * This class allows a single click and prevents multiple clicks on
 * the same button in rapid succession. Setting unclickable is not enough
 * because click events may still be queued up.
 * 
 * Override onOneClick() to handle single clicks. Call reset() when you want to
 * accept another click.
 */
public abstract class OnOneOffClickListener implements OnClickListener {
    private boolean clickable = true;

    /**
     * Override onOneClick() instead.
     */
    @Override
    public final void onClick(View v) {
        if (clickable) {
            clickable = false;
            onOneClick(v);
            //reset(); // uncomment this line to reset automatically
        }
    }

    /**
     * Override this function to handle clicks.
     * reset() must be called after each click for this function to be called
     * again.
     * @param v
     */
    public abstract void onOneClick(View v);

    /**
     * Allows another click.
     */
    public void reset() {
        clickable = true;
    }
}

사용법은 OnClickListener와 동일하지만 대신 OnOneClick ()을 재정의합니다.

OnOneOffClickListener clickListener = new OnOneOffClickListener() {
    @Override
    public void onOneClick(View v) {

        // Do stuff

        this.reset(); // or you can reset somewhere else with clickListener.reset();
    }
};
myButton.setOnClickListener(clickListener);

코드 주셔서 감사합니다. 여기에 작성한 내용을 기반으로 버튼이나 부모가 숨겨져 있으면 클릭을 방지하는 비슷한 클래스를 만들었습니다. 클릭 직후에 버튼을 숨기더라도 Android가 클릭을 대기시키는 것이 재미 있습니다.
nikib3ro

1
비슷한 솔루션이 있습니다-당신은 XML 로이 클래스를 사용할 수 있으며 그것은 당신을 위해 clickListeners를 래핑합니다 github.com/doridori/AndroidUtilDump/blob/master/android/src/…
Dori

2
이것은 좋은 솔루션이지만 onClick ()과 reset ()을 동기화해야합니다. 그렇지 않으면 더블 클릭이 여전히 몰래 들어올 수 있습니다.
Tom anMoney

6
@TomanMoney, 어떻게? 모든 클릭 이벤트가 단일 UI 스레드에서 발생하지 않습니까?
Ken

@ 도리 링크가 죽었다
naXa

36

Kotlin Extension FunctionsRxBinding을 사용 하여 매우 멋진 방법으로 할 수 있습니다

   fun View.clickWithDebounce(debounceTime: Long = 600L, action: () -> Unit): Disposable =
        RxView.clicks(this)
                .debounce(debounceTime, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { action() }

또는

fun View.clickWithDebounce(debounceTime: Long = 600L, action: () -> Unit) {
    this.setOnClickListener(object : View.OnClickListener {
        private var lastClickTime: Long = 0

        override fun onClick(v: View) {
            if (SystemClock.elapsedRealtime() - lastClickTime < debounceTime) return
            else action()

            lastClickTime = SystemClock.elapsedRealtime()
        }
    })
}

그리고 그냥 :

View.clickWithDebounce{ Your code }

over engenering
Serg Burlaka

3
Rx에 대한 디 바운스가 제대로 작동하지 않습니다. 대신 "ThrottleFirst"가 더 잘 맞아야합니다. 여기 demo.nimius.net/debounce_throttle의 차이점에 대한 예가 있습니다. 추신 : 실제로 clickWithDebounce 구현은 디 바운스가 아닌 스로틀 구현입니다.
krossovochkin

13

나는 또한 비슷한 문제로 실행되며 때로는 클릭이 2 번 발생하는 날짜 선택기 및 시간 선택기를 표시하고있었습니다. 나는 이것으로 그것을 해결했다

long TIME = 1 * 1000;
@Override
public void onClick(final View v) {
v.setEnabled(false);

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            v.setEnabled(true);
        }
    }, TIME);
}

요구 사항에 따라 시간을 변경할 수 있습니다. 이 방법은 저에게 효과적입니다.


시간이 지나면 버튼을 자동으로 다시 활성화하기 때문에 이것이 진정한 해결책입니다. 두 번 빠르게 클릭하면 다른 솔루션에서 버튼이 영구적으로 차단됩니다. 이 솔루션은 문제를 해결합니다! 감사합니다
Néstor

10

setEnabled(false) 나를 위해 완벽하게 작동합니다.

아이디어는 처음에 쓰고 버튼을 처음 클릭 { setEnabled(true); }할 때만 작성한다는 것 false입니다.


9

나는 그것이 오래된 질문이라는 것을 알고 있지만이 일반적인 문제를 해결하기 위해 찾은 최고의 솔루션을 공유합니다.

        btnSomeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Prevent Two Click
            Utils.preventTwoClick(view);
            // Do magic
        }
    });

그리고 Utils.java와 같은 다른 파일에서

    /**
 * Método para prevenir doble click en un elemento
 * @param view
 */
public static void preventTwoClick(final View view){
    view.setEnabled(false);
    view.postDelayed(new Runnable() {
        public void run() {
           view.setEnabled(true);
        }
    }, 500);
}

8

이 문제에 대한 실제 해결책은 버튼을 회색으로 표시하는 setEnabled (false) 및 두 번째 클릭을받을 수 없도록하는 setClickable (false)을 사용하는 것입니다.이 테스트를 한 결과 매우 효과적입니다.


7

누군가가 여전히 짧은 답변을 찾고 있다면 아래 코드를 사용할 수 있습니다

 private static long mLastClickTime = 0;
  if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) { // 1000 = 1second
         return;
    }
 mLastClickTime = SystemClock.elapsedRealtime();

이 코드는 내부에 갈 것이다 if statement사용자가 클릭 할 때마다 View within 1 second다음이 return;시작되고 더 코드가 시작되지 않습니다.


2
이것이 정답입니다. 매우 간단하고 매우 빠르게 클릭하더라도 작동합니다! 고마워
Geoffroy CALA 2011

7

K LEANEST 코 틀린 관용적 방법 :

class OnSingleClickListener(private val block: () -> Unit) : View.OnClickListener {

    private var lastClickTime = 0L

    override fun onClick(view: View) {
        if (SystemClock.elapsedRealtime() - lastClickTime < 1000) {
            return
        }
        lastClickTime = SystemClock.elapsedRealtime()

        block()
    }
}

fun View.setOnSingleClickListener(block: () -> Unit) {
    setOnClickListener(OnSingleClickListener(block))
}

용법:

button.setOnSingleClickListener { ... }

6

내 솔루션은 boolean변수 를 사용하려고 합니다.

public class Blocker {
    private static final int DEFAULT_BLOCK_TIME = 1000;
    private boolean mIsBlockClick;

    /**
     * Block any event occurs in 1000 millisecond to prevent spam action
     * @return false if not in block state, otherwise return true.
     */
    public boolean block(int blockInMillis) {
        if (!mIsBlockClick) {
            mIsBlockClick = true;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mIsBlockClick = false;
                }
            }, blockInMillis);
            return false;
        }
        return true;
    }

    public boolean block() {
        return block(DEFAULT_BLOCK_TIME);
    }
}

그리고 아래와 같이 사용 :

view.setOnClickListener(new View.OnClickListener() {
            private Blocker mBlocker = new Blocker();

            @Override
            public void onClick(View v) {
                if (!mBlocker.block(block-Time-In-Millis)) {
                    // do your action   
                }
            }
        });

업데이트 : 뷰 확장을 사용하는 Kotlin 솔루션

fun View.safeClick(listener: View.OnClickListener, blockInMillis: Long = 500) {
    var lastClickTime: Long = 0
    this.setOnClickListener {
        if (SystemClock.elapsedRealtime() - lastClickTime < blockInMillis) return@setOnClickListener
        lastClickTime = SystemClock.elapsedRealtime()
        listener.onClick(this)
    }
}

5

클릭 가드 는 버터 나이프와 잘 작동합니다

ClickGuard.guard(mPlayButton);

4
핸들 버튼을 두 번 클릭하기위한 별도의 통로? ha
Serg Burlaka

이 버튼을 사용자 정의 버튼 안에서 사용할 수 있습니까?
Ara Badalyan

@AraBadalyan '내부'는 무슨 뜻입니까? 가드 방법의 매개 변수로 사용자 정의 버튼을 전달하십시오. 그런 다음 버튼을 더블 클릭으로부터 보호 될 것입니다
thanhbinh84

onclick을 사용하는 모든 활동에 ClickGuard.guard (mPlayButton)을 추가하고 싶지 않습니다. CustomButton extent Button을 만들고 CustomGuard 안에 ClickGuard를 넣고 싶습니다. 그러나 CustomButton 생성자에 ClickGuard를 추가하면 작동하지 않습니다.
Ara Badalyan

@AraBadalyan 맞습니다. 그런 식으로 작동하지 않습니다.
thanhbinh84

5

내 상황에서 버튼보기를 사용하고 있었고 너무 빨리 클릭을하고있었습니다. 클릭 가능을 비활성화하고 몇 초 후에 다시 활성화하십시오 ...

기본적으로 뷰 onClickListener를 감싸는 래퍼 클래스를 만들었습니다. 원하는 경우 사용자 지정 지연을 설정할 수도 있습니다.

public class OnClickRateLimitedDecoratedListener implements View.OnClickListener {

    private final static int CLICK_DELAY_DEFAULT = 300;
    private View.OnClickListener onClickListener;
    private int mClickDelay;


        public OnClickRateLimitedDecoratedListener(View.OnClickListener onClickListener) {
            this(onClickListener, CLICK_DELAY_DEFAULT);
        }

        //customize your own delay
        public OnClickRateLimitedDecoratedListener(View.OnClickListener onClickListener, int delay) {
            this.onClickListener = onClickListener;
            mClickDelay = delay;
        }

        @Override
        public void onClick(final View v) {
            v.setClickable(false);
            onClickListener.onClick(v);

            v.postDelayed(new Runnable() {
                @Override
                public void run() {
                    v.setClickable(true);
                }
            }, mClickDelay);
        }
    }

그리고 간단히 말하면 다음과 같습니다.

mMyButton.setOnClickListener(new OnClickRateLimitedDecoratedListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 doSomething();
             }
         }));

또는 자신의 지연을 제공하십시오.

 mMyButton.setOnClickListener(new OnClickRateLimitedDecoratedListener(new View.OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         doSomething();
                     }
                 },1000));

업데이트 : 위의 RxJava가 널리 보급 된 방식은 약간 구식입니다. 다른 사람들이 언급했듯이 안드로이드에서는 스로틀을 사용하여 클릭 속도를 늦출 수 있습니다. 다음은 하나의 예입니다.

 RxView.clicks(myButton)
                    .throttleFirst(2000, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
                    .subscribe {
                        Log.d("i got delayed clicked")
                    }
        }

이 라이브러리를 사용할 수 있습니다. implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'


4
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            //to prevent double click
            button.setOnClickListener(null);
        }
    });

4

이 방법을 사용할 수 있습니다. 포스트 딜레이를 사용하면 더블 클릭 이벤트를 처리 할 수 ​​있습니다.

무효 debounceEffectForClick (보기) {

    view.setClickable(false);

    view.postDelayed(new Runnable() {
        @Override
        public void run() {
            view.setClickable(true);

        }
    }, 500);
}

4

간결한 인라인 코드 및 가변 더블 클릭 대기 시간을 허용하는 Kotlin 확장

fun View.setDoubleClickListener(listener: View.OnClickListener, waitMillis : Long = 1000) {
    var lastClickTime = 0L
    setOnClickListener { view ->
        if (System.currentTimeMillis() > lastClickTime + waitMillis) {
            listener.onClick(view)
            lastClickTime = System.currentTimeMillis()
        }
    }
}

용법:

anyView.setNoDoubleClickListener(View.OnClickListener { v ->
    // do stuff
})

또는

anyView.setNoDoubleClickListener(View.OnClickListener { v ->
    // do stuff
}, 1500)

놀랍게도 모든 사람이 이것을 사용해야합니다. 절대적으로 멋진 코드 조각이며 모든 사람들이 kotlin으로 마이그레이션 해야하는 큰 이유입니다.
Achmad Naufal Syafiq

waitMillis가 하드 코딩 된 경우 더 좋을 수 있습니다. 외부 괄호를 제거 할 수 있습니다.
WindRider

4

아래 코드는 사용자가 몇 초 안에 여러 번 클릭하는 것을 방지하고 3 초 후에 만 ​​허용합니다.

private long lastClickTime = 0;

View.OnClickListener buttonHandler = new View.OnClickListener() {
    public void onClick(View v) {
        // preventing double, using threshold of 3000 ms
        if (SystemClock.elapsedRealtime() - lastClickTime < 3000){
            return;
        }

        lastClickTime = SystemClock.elapsedRealtime();
    }
}

3

onResume에서 클릭 리스너를 설정하고 onPause에서 null을 null 처리하면 트릭도 수행됩니다.


3

나를 위해 타임 스탬프를 기억하고 그에 대한 확인 (이전 클릭 이후 1 초 이상 경과) 만 도움이되었습니다.


3

이것이 당신을 도울 수 있기를 바랍니다. 이벤트 핸들러에 코드를 넣으십시오.

// ------------------------------------------------ --------------------------------

    boolean hasTag = null != which.getTag( R.id.preventing_double_click_tag );

    if ( hasTag ) {
        // Do not handle again...
        return;
    } else {
        which.setTag( R.id.action, Boolean.TRUE );

        which.postDelayed( new Runnable() {
            @Override
            public void run() {
                which.setTag( R.id.action, null );
                Log.d( "onActin", " The preventing double click tag was removed." );
            }

        }, 2000 );
    }

3

onClick 메서드가 즉시 반환되지 않으면 이러한 제안 중 어느 것도 작동하지 않는다는 것을 알았습니다. 터치 이벤트는 Android에서 대기하고 다음 onClick은 첫 번째가 완료된 후에 만 ​​호출됩니다. (이것은 하나의 UI 스레드에서 수행되므로 실제로는 정상입니다.) onClick 함수가 완료되는 시간 + 주어진 onClick이 실행 중인지 표시하기 위해 하나의 부울 변수를 사용해야했습니다. onClickListener가 동시에 실행되는 것을 피하기 위해이 마커 속성은 모두 정적입니다. (사용자가 다른 버튼을 클릭하는 경우) OnClickListener를이 클래스로 간단하게 교체 할 수 있으며 onClick 메서드를 구현하는 대신 추상 oneClick () 메서드를 구현해야합니다.

    abstract public class OneClickListener implements OnClickListener {

    private static boolean started = false;
    private static long lastClickEndTime = 0;

    /* (non-Javadoc)
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    @Override
    final public void onClick(final View v) {
        if(started || SystemClock.elapsedRealtime()-lastClickEndTime <1000 ){
            Log.d(OneClickListener.class.toString(), "Rejected double click, " + new Date().toString() );
            return; 
        }
        Log.d(OneClickListener.class.toString(), "One click, start: " + new Date().toString() );
        try{
            started = true;
            oneClick(v);
        }finally{
            started = false;
            lastClickEndTime = SystemClock.elapsedRealtime();
            Log.d(OneClickListener.class.toString(), "One click, end: " + new Date().toString() );
        }
    }

    abstract protected void oneClick(View v);
}

3

이 작업을 수행하기 위해 jake wharton의 rx 바인딩을 사용할 수도 있습니다 . 다음은 연속 클릭 사이에 2 초 간격으로 채워지는 샘플입니다.

RxView.clicks(btnSave)
                .throttleFirst(2000, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept( Object v) throws Exception {
//handle onclick event here
                });

// 참고 :이 경우 Object v를 무시하고 항상 생각합니다.


3

Kotlin은 SafeClickListener 클래스를 만듭니다.

class SafeClickListener(
        private var defaultInterval: Int = 1000,
        private val onSafeCLick: (View) -> Unit
) : View.OnClickListener {
    private var lastTimeClicked: Long = 0    override fun onClick(v: View) {
        if (SystemClock.elapsedRealtime() - lastTimeClicked < defaultInterval) {
            return
        }
        lastTimeClicked = SystemClock.elapsedRealtime()
        onSafeCLick(v)
    }
}

baseClass 또는 다른 함수를 작성하십시오.

fun View.setSafeOnClickListener(onSafeClick: (View) -> Unit) {val safeClickListener = SafeClickListener {
        onSafeClick(it)
    }
    setOnClickListener(safeClickListener)
}

버튼 클릭시 사용

btnSubmit.setSafeOnClickListener {
    showSettingsScreen()
}

1
확장 기능이있는 가장 깨끗한 솔루션! 감사!
android_dev



2

Clickable을 false로 설정하면 첫 번째 더블 클릭에서 작동하지 않지만 후속 더블 클릭은 차단됩니다. 로딩 클릭 델리게이트가 처음으로 느려지고 두 번째 클릭이 처음 완료되기 전에 캡처되는 것처럼 보입니다.

        Button button = contentView.FindViewById<Button>(Resource.Id.buttonIssue);
        button.Clickable = false;
        IssueSelectedItems();
        button.Clickable = true;

2

나는 @ jinshiyi11 답변과 비슷한 두 개의 clases를 사용 하여이 문제를 해결하고 주석은 명시 적 클릭을 기반으로합니다. 다른 버튼을 원하면 버튼을 한 번만 클릭 할 수 있습니다. 다른 클릭을 원한다면 명시 적으로 표시해야합니다 .

/**
 * Listener que sólo permite hacer click una vez, para poder hacer click
 * posteriormente se necesita indicar explicitamente.
 *
 * @author iberck
 */
public abstract class OnExplicitClickListener implements View.OnClickListener {

    // you can perform a click only once time
    private boolean canClick = true;

    @Override
    public synchronized void onClick(View v) {
        if (canClick) {
            canClick = false;
            onOneClick(v);
        }
    }

    public abstract void onOneClick(View v);

    public synchronized void enableClick() {
        canClick = true;
    }

    public synchronized void disableClick() {
        canClick = false;
    }
}

사용 예 :

OnExplicitClickListener clickListener = new OnExplicitClickListener() {
    public void onOneClick(View v) {
        Log.d("example", "explicit click");
        ...
        clickListener.enableClick();    
    }
}
button.setOnClickListener(clickListener);

2
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {

    private final AtomicBoolean onClickEnabled = new AtomicBoolean(true);

    @Override
    public void onClick(View v) {
        Log.i("TAG", "onClick begin");
        if (!onClickEnabled.compareAndSet(true, false)) {
            Log.i("TAG", "onClick not enabled");
            return;
        }

        button.setEnabled(false);

        // your action here

        button.setEnabled(true);
        onClickEnabled.set(true);
        Log.i("TAG", "onClick end");
    }
});

뷰 리스너는 항상 단일 스레드 (메인)에서 호출되므로 사용 AtomicBoolean하면 실제로 도움이되지 않습니다.
WindRider

2

시도해보십시오. 작동 중입니다.

mButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {

                mSlotLayout.setEnabled(false);

        //      do your work here

                Timer buttonTimer = new Timer();
                buttonTimer.schedule(new TimerTask() {

                    @Override
                    public void run() {

                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                mButton.setEnabled(true);
                            }
                        });
                    }
                }, 500); // delay button enable for 0.5 sec
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.