본문 바로가기
Project/안드로이드 프로젝트(RandomColorChart)

Android Studio, Kotlin] 2. addOnTextChangeListener. EditText가 변경될 때 마다 이벤트를 발생시키는 함수

by 김마리님 2021. 1. 8.

다음 코드를 보면 화면에 입력된 숫자에 따라 RGB 코드를 받아 view 색이 변경되는 것을 볼 수 있다.

 

이것을 적용시키려면, 텍스트가 변경될 때마다 색상을 변화시켜야 하는데, 이를 도와주는 리스너가 addTextChangedListener이다. 

 

거두절미하고 코드를 보자.

package com.mary.kotlinprojectstudy.writing

import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.EditText
import com.mary.kotlinprojectstudy.R
import com.mary.kotlinprojectstudy.util.DlogUtil
import org.w3c.dom.Text

class WritingColorActivity : AppCompatActivity() {

    lateinit var editTextRed : EditText
    lateinit var editTextGreen : EditText
    lateinit var editTextBlue : EditText
    lateinit var viewPreviewColor : View

    override fun onCreate(savedInstanceState: Bundle?) {
...
    }

    private fun findView() {
...
    }

    private fun rgbTextWatcher() {
        editTextRed.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

            override fun afterTextChanged(s: Editable?) {

                if(editTextBlue.text.toString() == "" || editTextGreen.text.toString() == "") {
                    DlogUtil.d(TAG, "값이 비었음")
                    return
                }

                if(editTextRed.text.toString() == "") {
                    DlogUtil.d(TAG, "값 지웠음")
                    viewPreviewColor.setBackgroundResource(R.drawable.test_border)
                    return
                }

                val red : Int = Integer.parseInt(editTextRed.text.toString())
                val green : Int = Integer.parseInt(editTextGreen.text.toString())
                val blue : Int = Integer.parseInt(editTextBlue.text.toString())

                DlogUtil.d(TAG, "색 변경")
                viewPreviewColor.setBackgroundColor(Color.rgb(red, green, blue))

            }

        })

        editTextGreen.addTextChangedListener(object  : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

            override fun afterTextChanged(s: Editable?) {
                if(editTextRed.text.toString() == "" || editTextBlue.text.toString() == "") {
                    DlogUtil.d(TAG, "값이 비었음")
                    return
                }

                if(editTextGreen.text.toString() == "") {
                    DlogUtil.d(TAG, "값 지웠음")
                    viewPreviewColor.setBackgroundResource(R.drawable.test_border)
                    return
                }

                val red : Int = Integer.parseInt(editTextRed.text.toString())
                val green : Int = Integer.parseInt(editTextGreen.text.toString())
                val blue : Int = Integer.parseInt(editTextBlue.text.toString())

                DlogUtil.d(TAG, "색 변경")
                viewPreviewColor.setBackgroundColor(Color.rgb(red, green, blue))
            }

        })

        editTextBlue.addTextChangedListener( object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

            override fun afterTextChanged(s: Editable?) {
                if(editTextRed.text.toString() == "" || editTextGreen.text.toString() == "") {
                    DlogUtil.d(TAG, "값이 비었음")
                    return
                }

                if(editTextBlue.text.toString() == "") {
                    DlogUtil.d(TAG, "값 지웠음")
                    viewPreviewColor.setBackgroundResource(R.drawable.test_border)
                    return
                }

                val red : Int = Integer.parseInt(editTextRed.text.toString())
                val green : Int = Integer.parseInt(editTextGreen.text.toString())
                val blue : Int = Integer.parseInt(editTextBlue.text.toString())

                DlogUtil.d(TAG, "색 변경")
                viewPreviewColor.setBackgroundColor(Color.rgb(red, green, blue))
            }

        })
    }

    companion object {
        private const val TAG = "WritingColorActivity"
    }
}

 

object : TextWatcher로 세 매서드를 상속받는다.

beforeTextChanged 는 텍스트 변경 전에 호출되고,

onTextChanged는 텍스트 변경 중에 호출되고,

afterTextChanged는 텍스트 변경 후에 호출된다.

우리는 텍스트 변경 후 값을 받아 RGB 코드에 적용하기만 하면 되므로 afterTextChanged를 이용한다,

 

 


아래부터는 간단한 개인 코드 설명

 

색을 바꾸는데에 이용할 함수는 viewPreviewColor.setBackgroundColor(Color.rgb(red, green, blue)) 함수이다.

따라서, 값의 공백이 생기는 순간 오류메세지를 출력하므로 먼저 값을 넣기 전에 나머지 두 칸이 비어있는지 확인해야한다. 그래서 if문으로 칸이 비었는지 비어있지 않은지 평가하고 비었다면 return으로 함수를 종료한다.

                if(editTextRed.text.toString() == "" || editTextBlue.text.toString() == "") {
                    DlogUtil.d(TAG, "값이 비었음")
                    return
                }

 

코틀린의 장점은 자바와 다르게 eqaul을 굳이 사용하지 않아도 == 를 사용하면 내부적으로 equal과 동일하게 적용해 주소값과 문자열을 비교한다. 따라서, 굳이 equal을 사용하지 않아도 알아서 주소값이 다르다면 문자열을 비교해준다.

 

 

다음, (전 코드 길어지는게 귀찮아서 parseInt 한걸 새로운 Int 변수에 넣어서 그 값을 background에 넣었습니다. 이 과정을 거치지 않는다면...... 해보십시오 안해봤습니다. 근데 아마 null이라서 오류날거 같은데)

문자열을 정수로 파싱할때 해당 editText가 비었다면 null object exception을 출력하므로 텍스트를 다 지워 공백이 됐을 경우도 if문을 이용해 판단하고, 공백이라면 return으로 함수를 종료시킵니다.

                if(editTextGreen.text.toString() == "") {
                    DlogUtil.d(TAG, "값 지웠음")
                    viewPreviewColor.setBackgroundResource(R.drawable.test_border)
                    return
                }

당연히 이 때 값이 비었으므로 view도 원상태로 복구시켜야겠죠? 빈 색으로 변화시킵니다.

 

이제 두 조건이 종료되었으므로 값을 int로 파싱해서 setBackground를 하시면 됩니다.

반응형