Edited at

お手軽にAndroidのButtonの連打を防止してみた

More than 1 year has passed since last update.


目的


  • Androidアプリにおいて、ボタンを連打されると困るので、連打できないようにしたい。


実装!


Button(AppCompatButton)を継承したButtonクラスを追加


app/src/main/java/com/example/barrageguardbuttondemo/utils/BarrageGuardButton.java

package com.example.barrageguardbuttondemo.utils; // Replace with your package

import android.content.Context;
import android.os.Handler;
import android.support.v7.widget.AppCompatButton;
import android.util.AttributeSet;
import android.view.View;

/**
* 連打防止Buttonクラス
*/

public class BarrageGuardButton extends AppCompatButton {
public BarrageGuardButton(Context context) {
super(context);
}

public BarrageGuardButton(Context context, AttributeSet attrs) {
super(context, attrs);
}

public BarrageGuardButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

public void setOnClickListener(final View.OnClickListener listener) {
super.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {

view.setEnabled(false);
new Handler().postDelayed(new Runnable() {
public void run() {
view.setEnabled(true);
}
}, 3000L);

listener.onClick(view);
}
});
}
}



Layout xml にButtonを追加 or 既存のボタンのタグを置換


app/src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.example.barrageguardbuttondemo.MainActivity">

<com.example.barrageguardbuttondemo.utils.BarrageGuardButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click here"/>
</LinearLayout>



ClickListenerをセット


app/src/main/java/com/example/barrageguardbuttondemo/MainActivity.java

package com.example.barrageguardbuttondemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import com.example.barrageguardbuttondemo.utils.BarrageGuardButton;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

((BarrageGuardButton) findViewById(R.id.button1)).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "It works!!!", Toast.LENGTH_SHORT).show();
}
});
}
}


以上で完了です!これでボタンをタップすると一定時間enabled:falseになり、連打ができなくなります。

既存コードで実装する場合は、xmlのButtonタグを置換するだけで振る舞いを変えることができます。


おまけ

BarrageGuardButton は Buttonクラス(今回は android.support.v7.widget.AppCompatButton ) を継承しているので、そのままDataBindingの表記にも対応できます。


app/build.gradle

apply plugin: 'com.android.application'

android {

...

dataBinding {
enabled = true
}
}



app/src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<data>
<variable
name="activity"
type="com.example.barrageguardbuttondemo.MainActivity"/>
</data>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.example.barrageguardbuttondemo.MainActivity">

<com.example.barrageguardbuttondemo.utils.BarrageGuardButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{activity::onClickDemoButton}"
android:text="Click here"/>
</LinearLayout>
</layout>



app/src/main/java/com/example/barrageguardbuttondemo/MainActivity.java

package com.example.barrageguardbuttondemo;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

import com.example.barrageguardbuttondemo.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setActivity(this);
}

public void onClickDemoButton(View view) {
Toast.makeText(MainActivity.this, "It works!!!", Toast.LENGTH_SHORT).show();
}
}


こんな感じに書いてもバッチリ動作します!

DataBindingについてはこちら : https://developer.android.com

(日本語の方もだいぶ整ってきましたね)

一応サンプルプロジェクトをGitHubで公開しています : https://github.com/sasakii/BarrageGuardButtonDemo


動作確認

demo

※ GIFにしたせいで若干汚いですがご了承を