앱을 사용하다 보면 어떤 특정 상태에서만 버튼이 활성화되어 다음으로 이동할 수 있는 화면을 흔히 볼 수 있습니다.
이번 포스팅에서는 회원가입 과정에서 이메일과 비밀번호 입력 조건을 설정하고 조건에 부합하는 경우에만 버튼을 활성화시키는 방법에 대해 공부해 보겠습니다.
실행결과
회원가입 진행 과정에서 이메일 형식을 입력하고, 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가 되면 다시 버튼이 비활성화되는 것도 확인할 수 있습니다.
'Android' 카테고리의 다른 글
[안드로이드] ScrollView 안에 RecyclerView 구현 시 RecyclerView의 스크롤 막는 방법 (1) | 2023.02.06 |
---|---|
[안드로이드] 프로젝트를 Git에 Push할 때 원하는 정보 숨기는 방법(.gitIgnore) (0) | 2023.02.03 |
[안드로이드] Fragment에서 뒤로가기 처리하기 - onBackPressedDispatcher (0) | 2023.02.01 |
[안드로이드] Retrofit 사용 시 "Unable to create call adapter for retrofit2 xxx ..." 오류 해결방법 (1) | 2023.01.31 |
[안드로이드] 스피너(Spinner)를 이용해 드롭다운 메뉴 구현 및 커스텀하는 방법 (1) | 2023.01.19 |