본문 바로가기
Android

[안드로이드] 회원가입 과정에서 EditText 텍스트 변경상태 감지해서 버튼 활성화하기

by JongSeok 2023. 2. 2.

앱을 사용하다 보면 어떤 특정 상태에서만 버튼이 활성화되어 다음으로 이동할 수 있는 화면을 흔히 볼 수 있습니다.

이번 포스팅에서는 회원가입 과정에서 이메일과 비밀번호 입력 조건을 설정하고 조건에 부합하는 경우에만 버튼을 활성화시키는 방법에 대해 공부해 보겠습니다.

실행결과

회원가입 진행 과정에서 이메일 형식을 입력하고, 8자리 이상의 비밀번호와 비밀번호 확인이 일치하고, 이름과 생년월일이 입력되었을 경우에만 '회원가입 완료' 버튼의 색상을 변경하면서 활성화시키겠습니다.


SignupFragment

class SignupFragment : Fragment() {
    private var _binding : FragmentSignupBinding? = null
    private val binding get() = _binding!!
    private var emailFlag = false
    private var passFlag = false
    private var nameFlag = false
    private var birthFlag = false

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentSignupBinding.inflate(inflater, container,false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setSignupTextWatcher()
    }

    private fun setSignupTextWatcher() {
        // 이메일 입력 감지
        binding.etEmail.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                binding.tvWarnEmail.visibility = View.VISIBLE
                binding.ivCheckEmail.visibility = View.INVISIBLE
            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                if (binding.etEmail.text.contains('@')) {
                    binding.tvWarnEmail.visibility = View.INVISIBLE
                    binding.ivCheckEmail.visibility = View.VISIBLE
                    emailFlag = true
                } else {
                    binding.tvWarnEmail.visibility = View.VISIBLE
                    binding.ivCheckEmail.visibility = View.INVISIBLE
                    emailFlag = false
                }
            }
            override fun afterTextChanged(p0: Editable?) {
                setSignupBtnFlag()
            }
        })
        
        // 비밀번호 입력 감지
        binding.etPassword.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                binding.tvWarnPassword.visibility = View.VISIBLE
                binding.ivCheckPassword.visibility = View.INVISIBLE
            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                if (binding.etPassword.text.length>=8) {
                    binding.tvWarnPassword.visibility = View.INVISIBLE
                    binding.ivCheckPassword.visibility = View.VISIBLE
                } else {
                    binding.tvWarnPassword.visibility = View.VISIBLE
                    binding.ivCheckPassword.visibility = View.INVISIBLE
                }
            }
            override fun afterTextChanged(p0: Editable?) {
                setSignupBtnFlag()
            }
        })
        
        // 비밀번호 확인 입력 감지
        binding.etPasswordConfirm.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                binding.tvWarnPasswordConfirm.visibility = View.VISIBLE
                binding.ivCheckPasswordConfirm.visibility = View.INVISIBLE
            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                if (binding.etPassword.text.toString() == binding.etPasswordConfirm.text.toString()) {
                    binding.tvWarnPasswordConfirm.visibility = View.INVISIBLE
                    binding.ivCheckPasswordConfirm.visibility = View.VISIBLE
                    passFlag = true
                } else {
                    binding.tvWarnPasswordConfirm.visibility = View.VISIBLE
                    binding.ivCheckPasswordConfirm.visibility = View.INVISIBLE
                    passFlag = false
                }
            }
            override fun afterTextChanged(p0: Editable?) {
                setSignupBtnFlag()
            }
        })
        
        // 이름 입력 감지
        binding.etName.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                nameFlag = binding.etName.text.isNotEmpty()
            }
            override fun afterTextChanged(p0: Editable?) {
                setSignupBtnFlag()
            }
        })
        
        // 생년월일 입력 감지
        binding.etBirth.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                birthFlag = binding.etBirth.text.isNotEmpty()
            }
            override fun afterTextChanged(p0: Editable?) {
                setSignupBtnFlag()
            }
        })
    }
    
    private fun setSignupBtnFlag() {
    
        // 회원가입 버튼 활성화
        if (emailFlag && passFlag && nameFlag && birthFlag) {
            binding.btnSignupComplete.isEnabled = true
            
            binding.btnSignupComplete.setBackgroundResource(R.drawable.background_rec_10dp_red_stroke_red_soild)

            binding.btnSignupComplete.setOnClickListener {
                Toast.makeText(requireContext(),"회원가입이 완료되었습니다.",Toast.LENGTH_SHORT).show()
                requireActivity().supportFragmentManager.beginTransaction().remove(this).commit()
            }
        } else {
            binding.btnSignupComplete.setBackgroundResource(R.drawable.background_rec_10dp_grey_soild)
        }
    }
}

해당 화면인 프래그먼트의 전체 코드인데 중복되는 부분이 많아 일부분만 살펴보겠습니다.

private fun setSignupTextWatcher() {
    // 이메일 입력 감지
    binding.etEmail.addTextChangedListener(object : TextWatcher{
        // 텍스트 입력 전
        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            binding.tvWarnEmail.visibility = View.VISIBLE
            binding.ivCheckEmail.visibility = View.INVISIBLE
        }
        // 텍스트 입력 중
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            if (binding.etEmail.text.contains('@')) {
                binding.tvWarnEmail.visibility = View.INVISIBLE
                binding.ivCheckEmail.visibility = View.VISIBLE
                emailFlag = true
            } else {
                binding.tvWarnEmail.visibility = View.VISIBLE
                binding.ivCheckEmail.visibility = View.INVISIBLE
                emailFlag = false
            }
        }
        // 텍스트 입력 후
        override fun afterTextChanged(p0: Editable?) {
            setSignupBtnFlag()
        }
    })
    ...
}

EditText 컴포넌트의 경우 EditText에 입력되는 텍스트의 변경을 감지할 수 있는 addTextChangedListener를 제공합니다.

 

필요에 따라 beforeTextChanged, onTextChanged, afterTextChanged 메소드를 재정의하여 addTextChangedListener에 TextWatcher객체를 전달해주는 방식으로 사용합니다.

 

이메일을 입력하는 경우에는 '@'를 포함하면 올바른 형식이라 판단해 emailFlag를 true로 수정합니다.

그리고 텍스트 입력이 끝날 때마다 setSignupBtnFlag()를 호출해 버튼이 활성화 가능한 상태인지 확인합니다.

 

나머지 비밀번호, 이름, 생년월일의 addTextChangedListener도 이메일 입력 방식과 거의 동일합니다.

private fun setSignupBtnFlag() {
    // 회원가입 버튼 활성화
    if (emailFlag && passFlag && nameFlag && birthFlag) {
        binding.btnSignupComplete.isEnabled = true
        binding.btnSignupComplete.setBackgroundResource(R.drawable.background_rec_10dp_red_stroke_red_soild)

        binding.btnSignupComplete.setOnClickListener {
            Toast.makeText(requireContext(),"회원가입이 완료되었습니다.",Toast.LENGTH_SHORT).show()
            requireActivity().supportFragmentManager.beginTransaction().remove(this).commit()
        }
    } else {
        binding.btnSignupComplete.isEnabled = false
        binding.btnSignupComplete.setBackgroundResource(R.drawable.background_rec_10dp_grey_soild)
    }
}

emaliFlag, passFlag, nameFlag, birthFlag가 모두 true일 경우에만 버튼이 활성화되도록 설정합니다. 

 

각각의 Flag는 EditText의 addTextChangedListener에서 실시간으로 변경 상태를 감지하고 있기 때문에 모두 true인 상황에서 다시 어느 하나의 Flag라도 false가 되면 다시 버튼이 비활성화되는 것도 확인할 수 있습니다.

728x90
반응형