내가 구현하고자 한 것은 여러 EditText의 값이 모두 채워지면 하단 버튼이 활성화되도록 하는 것이었다.
하나의 EditText로 버튼을 활성화하는 자료는 많이 찾았지만,
여러 EditText가 모두 채워져야 버튼이 활성화되는 글은 찾지 못했다.
그러던 와중, 활용하면 좋을 것 같은 글을 발견했다.
https://ddolcat.tistory.com/576
해당 글은 EditWatcher
를 사용하는 내부 class를 사용하여 EditText를 추적하는 내용을 담고있었고, 이때 여러 EditText에 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?) { }
}
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 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 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))
}
}
}