[Android 앱 개발 입문] 과제 - 자기소개 앱 (2)기능 구현

0
post-thumbnail
post-custom-banner

🍥 구현 기능

  • 로그인 화면
    • 이름을 입력받기
      • 입력 칸이 비어있는 경우, 경고 메세지 출력하기
    • 비밀번호를 입력받기
      • 입력 칸이 비어있는 경우, 경고 메세지 출력하기
    • 로그인 버튼 클릭 이벤트 처리하기
      • 이름 입력 칸이 비어있는 경우, 경고 메세지 출력하기
      • 비밀번호 입력 칸이 비어있는 경우, 경고 메세지 출력하기
      • 이름 및 비밀번호 입력 칸이 비어있지 않은 경우, 로그인하기
      • 로그인에 실패한 경우, 경고 메세지 출력하기
      • 로그인에 성공한 경우, 홈 화면으로 이동하기
        • 홈 화면으로 이동하며, 로그인한 사용자 정보 넘겨주기
    • 회원가입 버튼 클릭 이벤트 처리하기
      • 회원가입 화면으로 이동하기
  • 홈 화면
    • 로그인한 사용자의 이름 출력하기
    • 로그인한 사용자의 이메일 출력하기
    • 종료 버튼 클릭 이벤트 처리하기
      • 로그인 화면으로 돌아가기
  • 회원가입 화면
    • 이름을 입력받기
      • 입력 칸이 비어있는 경우, 경고 메세지 출력하기
      • 이미 존재하는 이름일 경우, 경고 메세지 출력하기
    • 이메일을 입력받기
      • 입력 칸이 비어있는 경우, 경고 메세지 출력하기
    • 이메일 제공자 선택을 위한 Spinner 선택 이벤트 처리(⭐챌린지 과제)
      • '직접 선택' 옵션을 선택하면, 입력 칸 보이기
    • 비밀번호를 입력받기
      • 입력 칸이 비어있는 경우, 경고 메세지 출력하기
      • 10자 이상, 대문자 포함, 특수문자 포함하지 않는 경우, 안내 메세지 출력하기(⭐챌린지 과제)
    • 비밀번호 확인 입력 칸 만들기(⭐챌린지 과제)
      • 입력 칸이 비어있는 경우, 경고 메세지 출력하기
      • 비밀번호와 일치하지 않는 경우, 경고 메세지 출력하기
    • 회원가입 버튼 클릭 이벤트 처리하기
      • 회원가입에 실패한 경우, 경고 메세지 출력하기
      • 회원가입에 성공한 경우, 로그인 화면으로 돌아가기

🍥 구현하기

UserInfo 클래스

  • 회원 정보를 저장하기 위한 클래스
data class UserInfo(val name:String, val email:String, val password:String)

UserInfoManager 클래스

  • 회원 정보를 이용하는 기능을 구현하기 위한 클래스
  • 싱글톤으로 구현
  • 프로퍼티:
    • userInfoArray:Array
      회원가입된 사용자들의 정보(UserInfo)들의 목록
  • 메서드:
    • signIn(name: String, password: String):Boolean
      • 로그인을 구현한 메서드 -> 로그인 화면에서 사용
      • 사용자가 입력한 이름과 비밀번호를 매개변수로 받는다
        -> userInfoArray에서 같은 이름과 비밀번호를 가진 UserInfo가 있는지 찾는다
        -> 만약 있다면, 로그인할 수 있으므로 true를 반환한다
        -> 만약 없다면, 로그인할 수 없으므로 false를 반환한다
    • findUserEmail(name: String, password: String): String
      • 사용자의 이메일을 찾는 메서드 -> 홈 화면에서 사용
      • 로그인 한 사용자의 이름과 비밀번호를 매개변수로 받는다
        -> userInfoArray에서 같은 이름과 비밀번호를 가진 UserInfo를 찾는다
        -> 해당 UserInfo의 이메일을 반환한다
    • findSameName(name:String):Boolean
      • 같은 이름을 가진 UserInfo가 있는지 확인하는 메서드 -> 회원가입 화면에서 사용
      • 회원가입을 위해 사용자가 입력한 이름을 매개변수로 받는다
        -> userInfoArray에서 같은 이름을 가진 UserInfo를 찾는다
        -> 만약 같은 이름을 가진 UserInfo가 존재하면 true, 존재하지 않으면 false를 반환한다.
    • signUp(name:String, email:String, password: String)
      • 회원가입을 구현한 메서드 -> 회원가입 화면에서 사용
      • 회원가입을 위해 사용자가 입력한 이름, 이메일, 비밀번호를 매개변수로 받는다
        -> userInfoArray에 해당 사용자 정보를 담은 UserInfo를 생성하여 저장한다
class UserInfoManager private constructor() {
    private var userInfoArray = arrayOf<UserInfo>()

    companion object{
        private var instance: UserInfoManager? = null

        fun getInstance(): UserInfoManager {
            if(instance == null) instance = UserInfoManager()
            return instance!!
        }
    }

    fun signIn(name: String, password: String):Boolean{
        for(user in userInfoArray) {
            if((user.name == name) && (user.password == password)) return true
        }
        return false
    }

    fun findUserEmail(name: String, password: String): String {
        for(user in userInfoArray) {
            if((user.name == name) && (user.password == password)) return user.email
        }
        return ""
    }

    fun findSameName(name:String):Boolean{
        for(user in userInfoArray){
            if(user.name == name) return true
        }
        return false
    }

    fun signUp(name:String, email:String, password: String){
        userInfoArray += UserInfo(name, email, password)
    }
}

textViewExtensions.kt

  • 로그인 화면과 회원가입 화면에서,
    경고 메세지를 출력하기 위한 TextView를 조건에 따라 보여주기도 하고 숨기기도 해야한다
  • 그 때마다 TextView.visibility = View.VISIBLE 또는 TextView.visibility = View.INVISIBLE 를 작성해야한다
  • 코드를 더 간결하게 만들기 위해 이를 TextView의 확장함수로 정의해두었다
fun TextView.setVisible() {
    visibility = View.VISIBLE
}
fun TextView.setInvisible() {
    visibility = View.INVISIBLE
}

  • 로그인 화면과 회원가입 화면에서 EditText를 실시간으로 관찰하며,
    입력 칸이 비어있는지, 입력된 값이 유효한 값인지 확인해야 한다

  • 이를 위해 add TextChangedListner와 TextWatcher 인터페이스를 사용한다!

    • 방법 1. addTextChangedListner의 매개변수로 람다식 넘기기
      nameEditText.addTextChangedListener {
      	//onTextChanged에서 수행하고자 하는 코드 작성하기...
      }
    • 방법 2. addTextChangedListner의 매개변수로 TextWatcher 인터페이스를 구현하는 익명 object 넘기기
      editText.addTextChangedListner(object: TextWatcher{
              override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                  TODO("Not yet implemented")
              }
              override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                  TODO("Not yet implemented")
              }
              override fun afterTextChanged(p0: Editable?) {
                  TODO("Not yet implemented")
              }
        })
    • 방법 3. addTextChangedListner의 매개변수로 TextWatcher 인터페이스를 구현하는 객체 넘기기
    • 방법 4. addTextChangedListner의 매개변수로 TextWatcher 인터페이스를 구현하는 클래스의 객체 넘기기
  • 자기소개 앱에는 방법 3와 4을 사용하여 구현했다

    • 비밀번호 확인 EditText를 처리하기 위해 방법 3 사용
    • 이름, 이메일, 비밀번호 EditText를 처리하기 위해 방법 4 사용
      • 이름 입력을 처리하는 NameTextWatcher 클래스
      • 이메일 입력을 처리하는 EmailTextWatcher 클래스
      • 비밀번호 입력을 처리하는 PasswordTextWatcher 클래스

ActivityCode enum클래스

  • 이메일과 비밀번호 확인 입력은 회원가입 화면에서만 진행되지만,
    이름과 비밀번호 입력은 로그인 화면과 회원가입 화면에서 진행된다
  • NameTextWatcher가 이름을 입력받는 EditText의 입력 이벤트를 처리할 때
    • 로그인 화면: 이름이 공백인지 확인
    • 회원가입 화면: 이름이 공백인지 확인, 이미 존재하는 이름인지 확인
  • PasswordTextWatcher가 비밀번호를 입력받는 EditText의 입력 이벤트를 처리할 때
    • 로그인 화면: 비밀번호가 공백인지 확인
    • 회원가입 화면: 비밀번호가 공백인지 확인, 10자리 이상인지 & 대문자 포함하는지 & 특수문자 포함하는지 확인
  • 로그인 화면에서 사용될 때와 회원가입 화면에서 사용될 때 수행할 기능이 다르다
    -> 어느 화면에서 사용되는지 알 수 있어야 한다
    -> 이를 위해 어느 화면인지를 나타내는 enum 클래스를 만들어,
    NameTextWatcher와 PasswordTextWatcher의 생성자로 넘겨준다!
enum class ActivityCode (val code:Int) {
    SIGN_IN(1),
    SIGN_UP(2)
}

NameTextWatcher 클래스

  • 이름을 입력받는 EditText의 입력 이벤트를 처리하기 위한 TextWatcher 인터페이스 구현 클래스
  • 프로퍼티:
    • warningTextView:TextView
      • 이름 입력값이 유효하지 않을 경우 표시할 경고 메세지 TextView
    • activityCode:ActivityCode
      • 어느 화면에서 사용하는지 알기 위한 enum 클래스 값
      • ActivityCode.SIGN_IN인 경우, 로그인 화면
      • ActivityCode.SIGN_UP인 경우, 회원가입 화면
class NameTextWatcher(warningTextView: TextView, activityCode: ActivityCode): TextWatcher{
    private var warningTextView:TextView
    private var activityCode:ActivityCode

    init{
        this.warningTextView = warningTextView
        this.activityCode = activityCode
    }

    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) = Unit

    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        when(activityCode) {
            ActivityCode.SIGN_IN -> {
                //로그인하는 경우, 이름이 비어있는지만 확인
                if (p0.isNullOrBlank()){
                    warningTextView.apply{
                        text = resources.getText(R.string.empty_name_warning)
                        setVisible()
                    }
                    SignInActivity.isNameValid = false
                }
                else{
                    warningTextView.setInvisible()
                    SignInActivity.isNameValid = true
                }
            }
            ActivityCode.SIGN_UP -> {
                val userInfoManager = UserInfoManager.getInstance()
                //회원가입하는 경우,
                //(1) 이름이 비어있는지 확인
                if(p0.isNullOrBlank()){
                    warningTextView.apply{
                        text = resources.getText(R.string.empty_name_warning)
                        setVisible()
                    }
                    SignUpActivity.isNameValid = false
                }
                //(2) 이미 존재하는 이름인지 확인
                else if(userInfoManager.findSameName(p0.toString())){
                    warningTextView.apply{
                        text = resources.getText(R.string.same_name_warning)
                        setVisible()
                    }
                    SignUpActivity.isNameValid = false
                }
                else{
                    warningTextView.setInvisible()
                    SignUpActivity.isNameValid = true
                }
            }
        }
    }

    override fun afterTextChanged(p0: Editable?) = Unit
}

EmailTextWatcher 클래스

  • 이메일을 입력받는 EditText의 입력 이벤트를 처리하기 위한 TextWatcher 인터페이스 구현 클래스
  • 프로퍼티:
    • warningTextView:TextView
      • 이메일 입력값이 유효하지 않을 경우 표시할 경고 메세지 TextView
class EmailTextWatcher(warningTextView: TextView): TextWatcher {
    private var warningTextView: TextView

    init{
        this.warningTextView = warningTextView
    }

    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) = Unit

    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        if (p0.isNullOrBlank()){
            warningTextView.setVisible()
            SignUpActivity.isEmailValid = false
        }
        else{
            warningTextView.setInvisible()
            SignUpActivity.isEmailValid = true
        }
    }

    override fun afterTextChanged(p0: Editable?) = Unit
}

PasswordTextWatcher 클래스

  • 비밀번호를 입력받는 EditText의 입력 이벤트를 처리하기 위한 TextWatcher 인터페이스 구현 클래스
  • 프로퍼티:
    • warningTextView:TextView
      • 비밀번호 입력값이 유효하지 않을 경우 표시할 경고 메세지 TextView
    • activityCode:ActivityCode
      • 어느 화면에서 사용하는지 알기 위한 enum 클래스 값
      • ActivityCode.SIGN_IN인 경우, 로그인 화면
      • ActivityCode.SIGN_UP인 경우, 회원가입 화면
class PasswordTextWatcher(warningTextView: TextView, activityCode: ActivityCode) : TextWatcher {
    private var warningTextView: TextView
    private var activityCode: ActivityCode

    init {
        this.warningTextView = warningTextView
        this.activityCode = activityCode
    }

    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) = Unit

    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        when (activityCode) {
            ActivityCode.SIGN_IN -> {
                //로그인하는 경우, 비밀번호 비어있는 지만 확인
                if (p0.isNullOrBlank()) {
                    warningTextView.apply {
                        text = resources.getString(R.string.empty_password_warning)
                        setTextColor(resources.getColor(R.color.warning_color))
                        setVisible()
                    }
                    SignInActivity.isPasswordValid = false
                } else {
                    warningTextView.setInvisible()
                    SignInActivity.isPasswordValid = true
                }
            }

            ActivityCode.SIGN_UP -> {
                //회원가입하는 경우,
                //(1) 비어있는지 확인
                if (p0.isNullOrBlank()) {
                    warningTextView.apply {
                        text = resources.getString(R.string.empty_password_warning)
                        setTextColor(resources.getColor(R.color.warning_color))
                        setVisible()
                        SignUpActivity.isPasswordValid = false
                    }
                }
                //(2) 10자리 이상인지 확인
                else if (!isLongEnough(p0.toString())) {
                    warningTextView.apply {
                        text = resources.getString(R.string.password_length_information)
                        setTextColor(resources.getColor(R.color.information_color))
                        setVisible()
                        SignUpActivity.isPasswordValid = false
                    }
                }
                //(3) 대문자 포함하는지 확인
                else if (!containsUppercase(p0.toString())) {
                    warningTextView.apply {
                        text = resources.getString(R.string.password_uppercase_information)
                        setTextColor(resources.getColor(R.color.information_color))
                        setVisible()
                        SignUpActivity.isPasswordValid = false
                    }
                }
                //(4) 특수문자 포함하는지 확인
                else if (!containsSpecialChar(p0.toString())) {
                    warningTextView.apply {
                        text = resources.getString(R.string.password_special_char_information)
                        setTextColor(resources.getColor(R.color.information_color))
                        setVisible()
                        SignUpActivity.isPasswordValid = false
                    }
                }
                else warningTextView.setInvisible()
                SignUpActivity.isPasswordValid = true
            }
        }

    }

    override fun afterTextChanged(p0: Editable?) = Unit

    private fun isLongEnough(password: String): Boolean = (password.length >= 10)
    private fun containsUppercase(password: String): Boolean {
        for (ch in password) {
            if (('A'.code <= ch.code) && (ch.code <= 'Z'.code)) return true
        }
        return false
    }

    private fun containsSpecialChar(password: String): Boolean {
        val possibleSpecialChars =
            listOf('!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=')
        for (ch in password) {
            if (possibleSpecialChars.contains(ch)) return true
        }
        return false
    }
}

SignInActivity 클래스

  • 로그인 화면을 구현한 클래스
  • companion object 프로퍼티:
    • isNameValid
      • 입력한 이름이 유효한 값인지
      • NameTextWatcher 클래스에서 입력 이벤트를 처리하면서
        입력이 유효하면 true로 설정, 유효하지 않으면 false로 설정
    • isPasswordValid
      • 입력한 비밀번호가 유효한 값인지
      • PasswordTextWatcher 클래스에서 입력 이벤트를 처리하면서
        입력이 유효하면 true로 설정, 유효하지 않으면 false로 설정
class SignInActivity : AppCompatActivity() {
	//로그 출력할 때 사용할 tag 값
    private val TAG = "SignInActivity"

    private val nameEditText by lazy { findViewById<EditText>(R.id.et_name) }
    private val passwordEditText by lazy { findViewById<EditText>(R.id.et_password) }

    private val nameWarningTextView by lazy { findViewById<TextView>(R.id.tv_name_warning) }
    private val passwordWarningTextView by lazy { findViewById<TextView>(R.id.tv_password_warning) }

    private val signInWarningTextView by lazy { findViewById<TextView>(R.id.tv_sign_in_warning) }
    private val signInButton by lazy { findViewById<Button>(R.id.btn_sign_in) }
    private val signUpButton by lazy { findViewById<Button>(R.id.btn_sign_up) }

    companion object{
        var isNameValid = false
        var isPasswordValid = false
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sign_in)

        nameEditText.addTextChangedListener(
            NameTextWatcher(nameWarningTextView, ActivityCode.SIGN_IN))
        passwordEditText.addTextChangedListener(
            PasswordTextWatcher(passwordWarningTextView, ActivityCode.SIGN_IN))

        signInButton.setOnClickListener(signInOnClickListener)
        signUpButton.setOnClickListener {
            val intent = Intent(this, SignUpActivity::class.java)
            startActivity(intent)
        }
    }

    private val signInOnClickListener = object: OnClickListener{
        override fun onClick(p0: View?) {
            //로그인 하기 위해 모든 입력 유효한지 확인
            if (!isNameValid) {
                Log.d(TAG, "sign in button) name is empty")
                signInWarningTextView.apply{
                    text = resources.getText(R.string.empty_name_warning)
                    setVisible()
                }
                return
            }
            if (!isPasswordValid) {
                Log.d(TAG, "sign in button) password is empty")
                signInWarningTextView.apply{
                    text = resources.getText(R.string.empty_password_warning)
                    setVisible()
                }
                return
            }

            //로그인
            val name = nameEditText.text.toString()
            val password = passwordEditText.text.toString()
            if (UserInfoManager.getInstance().signIn(name, password)) {
                Log.d(TAG, "sign in button) sign in success")
                signInWarningTextView.setInvisible()

                val intent = Intent(applicationContext, HomeActivity::class.java)
                intent.putExtra("name", name)
                intent.putExtra("password", password)
                startActivity(intent)
            } else {
                Log.d(TAG, "sign in button) sign in fail")
                signInWarningTextView.apply{
                    text = resources.getText(R.string.sign_in_fail_warning)
                    setVisible()
                }
            }
        }
    }
}

HomeActivity 클래스

  • 홈 화면을 구현한 클래스
class HomeActivity : AppCompatActivity() {
	//로그 출력할 때 사용할 tag 값
    private val TAG = "HomeActivity"

    private val nameTextView:TextView by lazy{findViewById(R.id.tv_home_name)}
    private val emailTextView:TextView by lazy {findViewById(R.id.tv_home_email)}

    private val exitButton: Button by lazy{findViewById(R.id.btn_exit)}

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)

        val name = intent.getStringExtra("name")!!
        val password = intent.getStringExtra("password")!!
        val email = UserInfoManager.getInstance().findUserEmail(name, password)

        nameTextView.text = resources.getString(R.string.home_name, name)
        emailTextView.text = resources.getString(R.string.home_email, email)

        exitButton.setOnClickListener {
            finish()
        }
    }
}

SignUpActivity 클래스

  • 회원가입 화면을 구현한 클래스
  • companion object 프로퍼티:
    • isNameValid
      • 입력한 이름이 유효한 값인지
      • NameTextWatcher 클래스에서 입력 이벤트를 처리하면서
        입력이 유효하면 true로 설정, 유효하지 않으면 false로 설정
    • isEmailValid
      • 입력한 이메일이 유효한 값인지
      • EmailTextWatcher 클래스에서 입력 이벤트를 처리하면서
        입력이 유효하면 true로 설정, 유효하지 않으면 false로 설정
    • isPasswordValid
      • 입력한 비밀번호가 유효한 값인지
      • PasswordTextWatcher 클래스에서 입력 이벤트를 처리하면서
        입력이 유효하면 true로 설정, 유효하지 않으면 false로 설정
  • 프로퍼티:
    • isPasswordCheckValid
      • 입력한 비밀번호 확인이 유효한 값인지
      • 입력 이벤트를 처리하면서
        입력이 유효하면 true로 설정, 유효하지 않으면 false로 설정

📌참고자료: 스피너 | Android 개발자

1. 레이아웃에 스피너 추가하기

<Spinner
  android:id="@+id/planets_spinner"
  android:layout_width="match_parent"
  android:layout_height="wrap_content" />

2. 스피너 항목으로 사용할 문자열 배열 strings.xml에 추가하기

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string-array name="planets_array">
      <item>Mercury</item>
      <item>Venus</item>
      <item>Earth</item>
      <item>Mars</item>
      <item>Jupiter</item>
      <item>Saturn</item>
      <item>Uranus</item>
      <item>Neptune</item>
  </string-array>
</resources>

3. ArrayAdapter 인스턴스를 통해 스피너에 문자열 배열 제공하기

val spinner: Spinner = findViewById(R.id.spinner)
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter.createFromResource(
      this,
      R.array.planets_array,
      //선택된 항목이 스피너 컨트롤에 나타나는 방식 정의하는 레이아웃
      android.R.layout.simple_spinner_item 
).also { adapter ->
  // Specify the layout to use when the list of choices appears
  //스피너 선택 항목의 목록을 표시하는 데 사용하는 레이아웃
  adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
  // Apply the adapter to the spinner
  spinner.adapter = adapter
}

4. 사용자의 항목 선택 이벤트 수신하기

class SpinnerActivity : Activity(), AdapterView.OnItemSelectedListener {
  override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
      // An item was selected. You can retrieve the selected item using
      // parent.getItemAtPosition(pos)
  }
  override fun onNothingSelected(parent: AdapterView<*>) {
      // Another interface callback
  }
}
class SignUpActivity : AppCompatActivity() {
	//로그 출력할 때 사용할 tag 값
    private val TAG = "SignUpActivity"

    private val nameEditText by lazy{ findViewById<EditText>(R.id.et_name) }
    private val nameWarningTextView by lazy{ findViewById<TextView>(R.id.tv_name_warning)}

    private val emailEditText by lazy{ findViewById<EditText>(R.id.et_email)}
    private val emailProviderEditText by lazy{findViewById<EditText>(R.id.et_email_provider)}
    private val emailProviderSpinner by lazy{findViewById<Spinner>(R.id.spinner_email_provider)}
    private val emailWarningTextView by lazy{ findViewById<TextView>(R.id.tv_email_warning)}

    private val passwordEditText by lazy{ findViewById<EditText>(R.id.et_password)}
    private val passwordWarningTextView by lazy{ findViewById<TextView>(R.id.tv_password_warning)}

    private val passwordCheckEditText by lazy{ findViewById<EditText>(R.id.et_password_check)}
    private val passwordCheckWarningTextView by lazy{ findViewById<TextView>(R.id.tv_password_check_warning)}

    private val signUpWarningTextView by lazy{ findViewById<TextView>(R.id.tv_sign_up_warning) }
    private val signUpButton by lazy{ findViewById<Button>(R.id.btn_sign_up)}

    companion object{
        var isNameValid = false
        var isEmailValid = false
        var isPasswordValid = false
    }
    private var isPasswordCheckValid = false
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sign_up)

        nameEditText.addTextChangedListener(
            NameTextWatcher(nameWarningTextView, ActivityCode.SIGN_UP))
        emailEditText.addTextChangedListener(
            EmailTextWatcher(emailWarningTextView))
        passwordEditText.addTextChangedListener(
            PasswordTextWatcher(passwordWarningTextView, ActivityCode.SIGN_UP))
        passwordCheckEditText.addTextChangedListener(passwordCheckTextWatcher)
		
  		//Spinner
        ArrayAdapter.createFromResource(
            this,
            R.array.email_providers_array,
            android.R.layout.simple_spinner_item
        ).also { adapter ->
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            emailProviderSpinner.adapter = adapter
        }

        val emailProvider:String? = null
        emailProviderSpinner.onItemSelectedListener = spinnerOnItemSelectListener

        signUpButton.setOnClickListener(signUpOnClickListner)
    }
  
    private val passwordCheckTextWatcher = object : TextWatcher {
        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) = Unit
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            //비어있는지 확인
            if (p0.isNullOrBlank()) {
                passwordCheckWarningTextView.apply {
                    text = resources.getString(R.string.empty_password_warning)
                    setVisible()
                }
                isPasswordCheckValid = false
            }
            //비밀번호와 일치하는지 확인
            else if (p0.toString() != passwordEditText.text.toString()) {
                passwordCheckWarningTextView.apply {
                    text = resources.getString(R.string.password_different_warning)
                    setVisible()
                }
                isPasswordCheckValid = false
            } else {
                passwordCheckWarningTextView.setInvisible()
                isPasswordCheckValid = true
            }
        }
        override fun afterTextChanged(p0: Editable?) = Unit
    }
  
    private val spinnerOnItemSelectListener = object : AdapterView.OnItemSelectedListener {
        override fun onItemSelected(p0: AdapterView<*>?, view: View?, position: Int, id: Long) {
            Log.d(TAG, "email provider spinner) onItemSelected")
            if (position == emailProviderSpinner.adapter.count - 1) {
                emailProviderSpinner.visibility = View.GONE
                emailProviderEditText.visibility = View.VISIBLE
            }
        }

        override fun onNothingSelected(p0: AdapterView<*>?) {
            Log.d(TAG, "email provider spinner) onNothingSelected")
        }
    }
	
    private val signUpOnClickListner = object : OnClickListener {
        override fun onClick(p0: View?) {
            //회원가입하기 위해 모든 입력 유효한지 확인
            if (isNameValid && isEmailValid && isPasswordValid && isPasswordCheckValid) {
                Log.d(TAG, "sign up button) sign up success")
                signUpWarningTextView.setInvisible()

                //회원가입
                val name = nameEditText.text.toString()
                val password = passwordEditText.text.toString()
                var email = emailEditText.text.toString()
                //email 서비스 제공자 붙이기
                email += if (emailProviderSpinner.visibility == View.VISIBLE) {
                            emailProviderSpinner.selectedItem.toString()
                        } else {
                            emailProviderEditText.text?.toString() ?: ""
                        }

                val userInfoManager = UserInfoManager.getInstance()
                userInfoManager.signUp(name, email, password)

                finish()
            } else {
                Log.d(TAG, "sign up button) sign up fail")
                signUpWarningTextView.setVisible()
            }
        }
    }
}
profile
Be able to be vulnerable, in search of truth
post-custom-banner

0개의 댓글