Carrot
Android

[Android/Kotiln] Toast 중복(duration 중첩) 피하기

NaDuck 2022. 7. 22. 05:07

Toast 객체       

  • 유저에게 짧거나 간단한 알림을 띄우기 위해 사용

 

  • makeText로 Toast 메시지 박스 생성
    • 파라미터 duration: Toast.LENGTH_SHORT = 짧게 출력(약 2.5초) / Toast.LENGTH_LONG = 길게 출력(약 4.5초)

 

 

 


문제 파악

여러 이벤트들이 동시다발적으로 일어날 때,

가장 최근에 발생한 이벤트의 Toast 메시지를 즉각 화면에 띄울 수 있도록 하는 것이 (유저들을 위한 즉각적인 응답 측면에서) 중요하겠단 생각이 들었다. 

 

기존 Toast.makeText() 메소드만 사용했을 때,

동시다발적으로 Toast 메시지를 띄우면 파라미터로 들어가는 duration에 의해 duration이 계속 축적되어 

가장 마지막에 발생하는 Toast 메시지는 한참 나중에서야 뜨게 된다. 

예를 들어 10개의 이벤트에 대한 Toast 메시지를 출력하게 된다면, Toast.LENGTH_SHORT로 설정했을 때 족히 20초 이상은 걸린다. 

 

 

문제 해결

toast.cancel()을 이용한다. 

이는 전역변수로 운영되는 Toast 객체 변수 toast가 화면에 띄워지고 있을 때, 이를 취소시키는(즉 발동되면 fade-out으로 서서히 사라지는) 기능을 한다.

 

즉 이미 Toast 메시지가 화면에 나타나고 있으면서, 지금 또다른 이벤트의 Toast 메시지를 띄우게 될 경우, 

기존에 띄워진 Toast 메시지를 cancel 시킨 뒤, 현재 이벤트의 Toast 메시지를 새로 띄우면 된다.

 


Activity.kt

package com.example.learningandroid_hongdroid

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.View
import android.widget.Button
import android.widget.Toast

class ActivitySub : AppCompatActivity() {
    // 전역 변수로 Toast 객체 생성, null로 초기화 
    private var toast: Toast? = null

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

        val b = findViewById<Button>(R.id.btn_click)
        b.setOnClickListener {
            showToast(this, "test2 클릭")
        }
    }

    fun btn1Click(view: View) {
        showToast(this, "test1 클릭")
    }

    // showToast 사용자 정의 함수
    // step 1. toast?.cancel() = 앞서 먼저 띄워진 Toast 메시지가 있을 경우를 대비
    // step 2. 현재 눌린 버튼에 관련한 Toast 메시지 설정
    // step 3. Toast 메시지 띄우기
    private fun showToast(c: Context, message: String) {
        toast?.cancel()
        toast = Toast.makeText(c, message, Toast.LENGTH_SHORT)
        toast?.show()
    }
}

 

 

activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".ActivitySub">

    <!-- test1용 버튼 -->
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Test1"
        android:textAllCaps="false"
        android:onClick="btn1Click"/>

    <!-- test2용 버튼 -->
    <Button
        android:id="@+id/btn_click"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Test2"
        android:textAllCaps="false"/>

</LinearLayout>

 

* 다양한 실습을 위해 

'test1용 버튼'은 xml에서 onClick 속성을 통해 kt에서 btn1Click 함수를 정의하였고, 

'test2용 버튼'은 xml에서 id 속성을 kt에서 가져와, 이를 통해 setOnClickListener 함수를 정의하였다.