[Android/Kotlin] 여러 EditText 텍스트 입력 체크 및 버튼 활성화

코코아의 개발일지·2023년 6월 25일
0

Android-Kotlin

목록 보기
1/36
post-thumbnail

✍🏻 요구사항 분석

내가 구현하고자 한 것은 여러 EditText의 값이 모두 채워지면 하단 버튼이 활성화되도록 하는 것이었다.

하나의 EditText로 버튼을 활성화하는 자료는 많이 찾았지만,
여러 EditText가 모두 채워져야 버튼이 활성화되는 글은 찾지 못했다.
그러던 와중, 활용하면 좋을 것 같은 글을 발견했다.
https://ddolcat.tistory.com/576
해당 글은 EditWatcher를 사용하는 내부 class를 사용하여 EditText를 추적하는 내용을 담고있었고, 이때 여러 EditText에 EditWatcher를 단다면 내가 원하는 바를 이룰 수 있을 것 같았다.

구현 코드는 아래와 같다.

💻 구현 코드

1. EditWatcher 설정

inner class MyEditWatcher: TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
        // 값 변경 시 실행되는 함수
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            // 버튼 활성화 여부
            activateRegisterBtn()
        }
        override fun afterTextChanged(s: Editable?) { }
    }

2. EditText에 위의 EditWatcher 달기

private fun editTextChangedListener() {
        with(binding) {
            val watcher = MyEditWatcher()

            // 카테고리
            addMyTemplateCategoryEt.addTextChangedListener(watcher)
            // 목표
            addMyTemplateGoalEt.addTextChangedListener(watcher)
            // 기간
            addMyTemplatePeriodEt.addTextChangedListener(watcher)
            // 투두
            for (i: Int in todoList.indices) {
                todoList[i].addTextChangedListener(watcher)
            }
        }
    }

3 . EditText의 값에 따라 버튼 활성화 여부 체크

private fun activateRegisterBtn() {
        with(binding) {

            val category = addMyTemplateCategoryEt.text.toString()
            val goal = addMyTemplateGoalEt.text?.count()
            val period = addMyTemplatePeriodEt.text?.count()
            var todoOk = false
            for (i: Int in todoList.indices) {
                Log.d("AddMyTempAct", "todoText = ${todoList[i].text}")
                if (todoList[i].text.isNotEmpty()) {
                    todoOk = true
                }
            }

            if (category != "" && goal != 0 && period != 0 && todoOk) {
                changeButtonState(true)
            } else changeButtonState(false)
        }
    }

버튼 활성화를 하는 로직은 다음 두 조건을 모두 만족해야 했다.

  • 카테고리, 목표, 기간 EditText 값이 모두 채워져 있음
  • 투두 리스트 EditText 중 하나라도 값이 있음 (투두는 1~6개까지 가능)

4. 버튼 활성화

private fun changeButtonState(status: Boolean) {
        val btn = listOf(binding.addMyTemplateRegisterBtn, binding.addMyTemplateEditBtn)
        // 버튼 상태 변경
        if(status) {  // 활성화 상태
            for (i in btn) {
                i.isClickable = true
                i.isEnabled = true
                i.setTextColor(ContextCompat.getColor(this, R.color.text_01))
                i.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.Jblue))
            }
        } else {  // 비활성화 상태
            for (i in btn) {
                i.isClickable = false
                i.isEnabled = false
                i.setTextColor(ContextCompat.getColor(this, R.color.gray_text_btn))
                i.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.gray_template))
            }
        }
    }

내 경우엔 같은 코틀린 파일에서 등록과 수정 모드를 따로 나누어 버튼을 구분해놨기에,
(효율적이지 않을지는 몰라도) 앞선 3번의 버튼 활성화 조건에 따라 등록 버튼과 수정 버튼의 상태를 다음과 같이 설정해주었다.
1. 버튼 클릭 가능 및 활성화
2. 버튼 텍스트 색 변경
3. 버튼 배경색 변경

👩🏻‍💻 전체 코드

class AddMyTemplateActivity : BaseActivity<ActivityAddMyTemplateBinding>(ActivityAddMyTemplateBinding::inflate) {

    private lateinit var todoList : List<EditText>

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val spf = getSharedPreferences(KEY_PREFS, Context.MODE_PRIVATE)

        val templateIdx = spf.getInt(KEY_IDX, 0)
        val isEditable = spf.getBoolean(KEY_EDITABLE, false)

        Log.d("AddMyTemplateActivity", "넘겨받은 idx: ${templateIdx}")

        with(binding) {
            todoList = listOf(
                addMyTemplateTodo1Et,
                addMyTemplateTodo2Et,
                addMyTemplateTodo3Et,
                addMyTemplateTodo4Et,
                addMyTemplateTodo5Et,
                addMyTemplateTodo6Et
            )
        }

        if (isEditable) {
            Log.d("AddMyTemplateActivity", "편집 모드입니다")
            editingMode()
        } else {
            // 투두 추가하기
            onClickAddTodoBtn(todoCount)
        }
        
        // EditText 버튼 활성화 여부 체크
        editTextChangedListener()
    }
    
    inner class MyEditWatcher: TextWatcher {
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
        // 값 변경 시 실행되는 함수
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            // 버튼 활성화 여부
            activateRegisterBtn()
        }
        override fun afterTextChanged(s: Editable?) { }
    }
    
    private fun activateRegisterBtn() {
        with(binding) {

            val category = addMyTemplateCategoryEt.text.toString()
            val goal = addMyTemplateGoalEt.text?.count()
            val period = addMyTemplatePeriodEt.text?.count()
            var todoOk = false
            for (i: Int in todoList.indices) {
                Log.d("AddMyTempAct", "todoText = ${todoList[i].text}")
                if (todoList[i].text.isNotEmpty()) {
                    todoOk = true
                }
            }

            if (category != "" && goal != 0 && period != 0 && todoOk) {
                changeButtonState(true)
            } else changeButtonState(false)
        }
    }

    private fun editTextChangedListener() {
        with(binding) {
            val watcher = MyEditWatcher()

            // 카테고리
            addMyTemplateCategoryEt.addTextChangedListener(watcher)
            // 목표
            addMyTemplateGoalEt.addTextChangedListener(watcher)
            // 기간
            addMyTemplatePeriodEt.addTextChangedListener(watcher)
            // 투두
            for (i: Int in todoList.indices) {
                todoList[i].addTextChangedListener(watcher)
            }
        }
    }

    private fun changeButtonState(status: Boolean) {
        val btn = listOf(binding.addMyTemplateRegisterBtn, binding.addMyTemplateEditBtn)
        // 버튼 상태 변경
        if(status) {  // 활성화 상태
            for (i in btn) {
                i.isClickable = true
                i.isEnabled = true
                i.setTextColor(ContextCompat.getColor(this, R.color.text_01))
                i.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.Jblue))
            }
        } else {  // 비활성화 상태
            for (i in btn) {
                i.isClickable = false
                i.isEnabled = false
                i.setTextColor(ContextCompat.getColor(this, R.color.gray_text_btn))
                i.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.gray_template))
            }
        }
    }

📚 참고 자료

profile
안드로이드 개발자를 꿈꾸는 학생입니다

0개의 댓글