본문 바로가기
안드로이드 코틀린

[Kotlin][Android] 안드로이드 연속 클릭 막기

by teamnova 2022. 7. 22.

안녕하세요.

종종 특정 뷰에 대한 연속 클릭을 일정시간 동안 막고 싶을 때가 있죠.

(ex. 클릭 될 뷰에 한 번만 실행되어야 하는 로직이 연결되어 있거나 뷰를 클릭해서 새 창을 띄울때 실수로 두번 눌러도 하나만 띄우고 싶을때)

그 때 사용할 수 있는 코드에 대해 알아보겠습니다.  

 

1. OnClickListener를 상속받은 클래스를 하나 만들어줍니다. 

import android.util.Log
import android.view.View

class OnSingleClickListener(private val clickListener: View.OnClickListener) : View.OnClickListener {

    companion object {
        const val CLICK_INTERVAL: Long = 3000 //클릭 간 간격(3초)
        const val TAG = "OnSingleClickListener" //로그 확인을 위한 string
    }

    private var clickable = true //클릭 가능한 타이밍

    //클릭 시
    override fun onClick(v: View?) {
        if (clickable) {
            clickable = false
            v?.run {
                postDelayed({
                    clickable = true
                }, CLICK_INTERVAL)
                clickListener.onClick(v)
            }
        } else {
            Log.d(TAG, "waiting for a while")
        }
    }
}

fun View.setOnSingleClickListener(action: (v: View) -> Unit) {
    val listener = View.OnClickListener { action(it) }
    setOnClickListener(OnSingleClickListener(listener))
}

CLICK_INTERVAL 자리에 원하는 시간을 넣으시면 됩니다.

 

 

2. 필요한 뷰에 setOnclickListener 대신에 위 클래스에서 생성한 setOnSingleClickListner를 사용해줍니다.

class MainActivity : AppCompatActivity() {

    private val TAG = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btnTest1 = findViewById<Button>(R.id.btn_test1)
        val btnTest2 = findViewById<Button>(R.id.btn_test2)

        btnTest1.setOnClickListener {
            Log.d(TAG,"1번 클릭함")
        }

        btnTest2.setOnSingleClickListener{
            Log.d(TAG,"2번 클릭함")
        }
    }
}

저는 테스트를 위해 1번 버튼(btnTest1)에는 일반 클릭 리스너를 달고 2번 버튼(btnTest2)에는 싱글클릭리스너를 달았습니다.

 

 

[테스트 영상]

-> 1번 버튼을 클릭하면 로그가 바로바로 찍히지만

    2번 클릭은 일정시간동안 '"waiting for a while"가 찍히고 시간이 지나야 "2번 클릭함"이 찍히는 걸 확인할 수 있습니다.

 

 

[전체 코드]

MainActivity.kt

import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private val TAG = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btnTest1 = findViewById<Button>(R.id.btn_test1)
        val btnTest2 = findViewById<Button>(R.id.btn_test2)

        btnTest1.setOnClickListener {
            Log.d(TAG,"1번 클릭함")
        }

        btnTest2.setOnSingleClickListener{
            Log.d(TAG,"2번 클릭함")
        }
    }
}

 

OnSingleClickListener.kt

import android.util.Log
import android.view.View

class OnSingleClickListener(private val clickListener: View.OnClickListener) : View.OnClickListener {

    companion object {
        const val CLICK_INTERVAL: Long = 3000 //클릭 간 간격(3초)
        const val TAG = "OnSingleClickListener" //로그 확인을 위한 string
    }

    private var clickable = true //클릭 가능한 타이밍

    //클릭 시
    override fun onClick(v: View?) {
        if (clickable) {
            clickable = false
            v?.run {
                postDelayed({
                    clickable = true
                }, CLICK_INTERVAL)
                clickListener.onClick(v)
            }
        } else {
            Log.d(TAG, "waiting for a while")
        }
    }
}

fun View.setOnSingleClickListener(action: (v: View) -> Unit) {
    val listener = View.OnClickListener { action(it) }
    setOnClickListener(OnSingleClickListener(listener))
}

 

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:orientation="vertical"
    tools:context=".MainActivity"
    android:gravity="center"
    android:padding="10dp">
    
    <Button
        android:id="@+id/btn_test1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="test1"/>

    <Button
        android:id="@+id/btn_test2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="test2"/>

</LinearLayout>