본문 바로가기

Android Project

[Android / Kotlin] SNS 앱 팀 프로젝트 - 회원가입, 로그인 / 마이페이지

이번에는 회원가입,로그인 페이지를 만들어볼건데

먼저 메인엑티비티에서 프로필 이미지를 클릭하면 회원가입과 로그인을 할 수 있는 페이지로 이동할것이기 때문에 먼저 메인엑티비티에 추가로 디자인해줄것이다

 

 

# MainActivity에 디자인추가

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_linearlayout"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="@color/whisper"
        android:padding="10dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/main_music_imageview"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginLeft="10dp"
            android:src="@drawable/ic_music"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/main_profile_textview"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:minHeight="25dp"
            android:autoSizeTextType="uniform"
            android:layout_marginRight="10dp"
            android:gravity="end"
            android:text="@string/intro"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="@+id/main_profile_imagebutton"
            app:layout_constraintRight_toLeftOf="@id/main_profile_imagebutton"
            app:layout_constraintTop_toTopOf="@id/main_profile_imagebutton" />

        <ImageButton
            android:id="@+id/main_profile_imagebutton"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:background="@color/transparent"
            android:scaleType="fitXY"
            android:src="@drawable/ic_user"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />


    </androidx.constraintlayout.widget.ConstraintLayout>

    <FrameLayout
        android:id="@+id/main_framelayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/main_bottomnavgation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/main_linearlayout"
        app:layout_constraintVertical_bias="0.0">
    </FrameLayout>


    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/main_bottomnavgation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/menu" />


</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml

activity_main.xml

 

이런식으로 저번에 디자인해줬던 메인엑티비티에 상단 레이아웃을 추가로 디자인해줬다

 

그리고 MainActivity로 가서 프로필이미지를 클릭했을때 FirstActivity로 이동하도록해준다

class MainActivity : AppCompatActivity() {

    lateinit var emailData : String
    lateinit var nameData : String
    lateinit var intentToLogin : Intent
    lateinit var profileBtn : ImageButton
    lateinit var profileTextview : TextView

	...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
		
        ...


        setContentView(R.layout.activity_main)
        
        profileBtn = findViewById(R.id.main_profile_imagebutton)

		// 프로필 클릭했을때 FirstActivity로 이동
        profileBtn.setOnClickListener {
            intentToLogin = Intent(this,FirstActivity::class.java)
            startActivity(intentToLogin)
        }
        
		...
        
    }
    
		...
        
}

MainActivity.kt

 

 

 

# FirstActivity

activity_first부분은 아래와같이 디자인해줬고 로그인버튼을 누르면 LoginActivity로 이동, 회원가입버튼을 누르면 SignUpActivity로 이동하도록 코드를 짜줬다

activity_first.xml

 

class FirstActivity : AppCompatActivity() {
    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_first)

        val loginButton: Button = findViewById(R.id.main_login_button)
        val signUpButton: Button = findViewById(R.id.main_signup_button)

        val loginIntent = Intent(this@FirstActivity, LoginActivity::class.java)
        val signUpIntent = Intent(this@FirstActivity, SignUpActivity::class.java)

        loginButton.setOnClickListener{
            startActivity(loginIntent)
        }

        signUpButton.setOnClickListener{
            startActivity(signUpIntent)
        }

    }

}

FirstActivity.kt

 

 

 

# SignUpActivity

디자인은 아래와같이 해줬다

activity_signup.xml

 

 

SignUpActivity 전체 코드이다

class SignUpActivity : AppCompatActivity() {

    private lateinit var signupEmailEdittext: EditText
    private lateinit var signupPasswordEdittext: EditText
    private lateinit var signupCheckpasswordEdittext: EditText
    private lateinit var signupNameEdittext: EditText
    private lateinit var signupSignupButton: Button
    private lateinit var signupBackButton: ImageButton

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

        signupBackButton = findViewById(R.id.signup_back_button)
        signupSignupButton = findViewById(R.id.signup_signup_button)

        signupEmailEdittext = findViewById(R.id.signup_email_edittext)
        signupPasswordEdittext = findViewById(R.id.signup_password_edittext)
        signupCheckpasswordEdittext = findViewById(R.id.signup_checkpassword_edittext)
        signupNameEdittext = findViewById(R.id.signup_name_edittext)



        fun checkEmail():Boolean {
            // 이메일 형식을 검사하는 정규식
            val emailValidation = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"
            val email = signupEmailEdittext.text.toString().trim()  //공백제거
            val p = Pattern.matches(emailValidation, email)       // emailValidation과 email이 서로 패턴이 맞는지 확인
            if (p) {
                // 이메일 형식이 올바를경우 -> 텍스트색상 black
                signupEmailEdittext.setTextColor(getColor(R.color.black))
                return true
            } else {
                // 이메일 형식이 올바르지 않을경우 -> 텍스트색상 red
                signupEmailEdittext.setTextColor(getColor(R.color.red))
                return false
            }
        }

        // 이메일 유효성 검사
        // signupEmailEdittext에 TextWatcher 연결
        signupEmailEdittext.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                // text가 변경된 후 호출
            }
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                // text가 변경되기 전 호출
            }
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // text가 바뀔 때마다 호출
                checkEmail()
            }
        })




        fun isRegularPwd(editText: EditText):Boolean {
            val pwd = editText.text.toString().trim()
            // 비밀번호 형식을 검사하는 정규식
            val pwdPattern = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$@$!%*#?&.])[A-Za-z[0-9]$@$!%*#?&.]{8,16}$"
            val pattern = Pattern.matches(pwdPattern,pwd)
            if(pattern) {
                //유효성 검사 결과 정해진 비밀번호 형식일 경우 -> 텍스트색상 black
                editText.setTextColor(getColor(R.color.black))
                return true
            } else {
                // 유효성 검사 결과 비밀번호 형식이 아닐경우 -> 텍스트색상 red
                editText.setTextColor(getColor(R.color.red))
                return false
            }
        }

        // 비밀번호 유효성 검사
        // signupPasswordEdittext에 TextWatcher 연결
        signupPasswordEdittext.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // 텍스트가 변경될 때마다 호출
                // 비밀번호를 입력할 때 실시간으로 비밀번호 형식을 검사
                isRegularPwd(signupPasswordEdittext)
            }


        })


        // 비밀번호 확인 유효성 검사
        // signupCheckpasswordEdittext에 TextWatcher 연결
        signupCheckpasswordEdittext.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // 텍스트가 변경될 때마다 호출된다.
                // 비밀번호를 입력할 때 실시간으로 비밀번호 형식을 검사
                isRegularPwd(signupCheckpasswordEdittext)
            }


        })

        
        signupBackButton.setOnClickListener {
            finish()
        }

        signupSignupButton.setOnClickListener {
        	// 정보를 다 입력하지 않은 경우
            if (signupEmailEdittext.length() == 0 || signupPasswordEdittext.length() == 0 || signupCheckpasswordEdittext.length() == 0 || signupNameEdittext.length() == 0) {
                Toast.makeText(this, getString(R.string.request_info), Toast.LENGTH_SHORT).show()
            // '비밀번호'와 '비밀번호 확인' 데이터가 다른 경우
            } else if (signupPasswordEdittext.text.toString() != signupCheckpasswordEdittext.text.toString()) {
                Toast.makeText(this, getString(R.string.password_check), Toast.LENGTH_SHORT).show()
            } else {
                intent = Intent(this, FirstActivity::class.java)
                intent.putExtra("email",signupEmailEdittext.text.toString())
                intent.putExtra("password",signupPasswordEdittext.text.toString())
                intent.putExtra("name",signupNameEdittext.text.toString())
                startActivity(intent)
            }
        }
    }



}

SignUpActivity.kt

 

여기서는 정보를 다 입력하지 않은 경우, 비밀번호와 비밀번호 확인의 내용이 다른경우에는 회원가입버튼을 눌러도 안넘어가게 했고, 그게 아닐때만 회원가입버튼 클릭했을때 FirstActivity로 이동하게 했다

그리고 이동할때 putExtra를 사용해서 FirstActivity로 email, password,name 데이터를 넘겨주었다

 

-  TextWatcher를 사용한 이메일과 비밀번호 유효성 검사

그리고 TextWatcher를 사용해서 이메일과 비밀번호의 유효성 검사도 진행해줬다

 

1. 이메일 형식과 비밀번호 형식을 확인해주는 함수를 만든다

2. EditText에 입력할때마다 이메일형식에 맞는지 확인한다 (맞은경우- textColor red / 틀린경우- textColor black)

 

이메일 형식과 비밀번호 형식을 확인해주는 함수를 만드는데

이메일 형식을 검사하는 정규식과 비밀번호 형식을 검사하는 정규식이 다르다

// 이메일 형식 검사 정규식
val emailValidation = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"
// 비밀번호 형식을 검사 정규식
val pwdPattern = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$@$!%*#?&.])[A-Za-z[0-9]$@$!%*#?&.]{8,16}$"

 

이런식으로 형식을 검사한다음 형식에 맞으면 텍스트컬러 black, 아니면 텍스트컬러 red로 설정해주면된다

 

그리고 EditText item에 TextWatcher를 연결해줘야하는데

우리는 텍스트가 바뀔때마다 형식을 검사해야되니깐 onTextChanged함수에 방금 만든 형식을 확인해주는 함수를 호출해준다!!

 

# 이메일,비밀번호 유효성검사 실행화면

 

 

 

 

 

# FirstActivity

이제 다시 FirstActivity로 와서 아까 SignUpActivity에서 보낸 데이터를 받아와주고 

그 데이터를 다시 LoginActivity로 또 넘겨준다 (최종적으로는 MypageFragment에 데이터를 받아와서 뿌려줘야함)

 

그리고 로그인버튼을 눌렀을때 화면전환 애니메이션도 적용해줬다

class FirstActivity : AppCompatActivity() {
    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_first)

        val loginButton: Button = findViewById(R.id.main_login_button)
        val signUpButton: Button = findViewById(R.id.main_signup_button)

        val loginIntent = Intent(this@FirstActivity, LoginActivity::class.java)
        val signUpIntent = Intent(this@FirstActivity, SignUpActivity::class.java)

        // SignUpActivity에서 보낸 데이터 받아오기
        val emailData = intent.getStringExtra("email")
        val passwordData = intent.getStringExtra("password")
        val nameData = intent.getStringExtra("name")


        loginButton.setOnClickListener{
            // LoginActivity로 데이터 넘겨주기
            loginIntent.putExtra("email",emailData)
            loginIntent.putExtra("password",passwordData)
            loginIntent.putExtra("name",nameData)
            startActivity(loginIntent)


            // 화면전환 애니메이션
            if (Build.VERSION.SDK_INT >= 34) {
                overrideActivityTransition(Activity.OVERRIDE_TRANSITION_OPEN, R.anim.from_left_enter, R.anim.to_left_exit)
            } else {
                overridePendingTransition(R.anim.from_down_enter, R.anim.none)
            }


        }

        signUpButton.setOnClickListener{
            startActivity(signUpIntent)
        }

    }

}

FirstActivity.kt

 

# 화면전환 애니메이션 적용

작성하기 

 

 

 

 

 

# LoginActivity

LoginActivity에서는 FirstActivity에서 보낸 데이터를 받아와준다

그리고 정보를 다 입력하지 않은경우, 회원가입에서 받은 정보가 아닐경우 토스트메시지를 출력해주고

저 경우가 아닐경우만 MainActivity로 이동하면서 email,name 데이터를 전달해주도록 했다

그리고 LoginAcitivty에서도 역시 이메일과 비밀번호 유효성검사를 진행해주었다

class LoginActivity : AppCompatActivity() {

    private lateinit var loginEmailEdittext: EditText
    private lateinit var loginPasswordEdittext: EditText
    private lateinit var loginNameEdittext: EditText

    companion object {
        // 정보가 누적될 수 있도록 companion object로 설정
        private var emailList = mutableListOf<String>()
        private var passwordList = mutableListOf<String>()
        private var nameList = mutableListOf<String>()
    }

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

        val loginBackButton: ImageButton = findViewById(R.id.login_back_button)
        val loginButton: Button = findViewById(R.id.login_login_button)
        loginEmailEdittext = findViewById(R.id.login_email_edittext)
        loginPasswordEdittext = findViewById(R.id.login_password_edittext)
        loginNameEdittext = findViewById(R.id.login_name_edittext)

        // FirstActivity에서 보낸 데이터 받아오기
        val emailData = intent.getStringExtra("email")
        emailList.add(emailData ?: "-1")

        val passwordData = intent.getStringExtra("password")
        passwordList.add(passwordData ?: "-1")

        val nameData = intent.getStringExtra("name")
        nameList.add(nameData ?: "-1")


        loginBackButton.setOnClickListener {
            finish()
            //화면전환 애니메이션
            overridePendingTransition(R.anim.from_left_enter, R.anim.to_left_exit)
        }


        loginButton.setOnClickListener {
            // 정보를 다 입력하지 않은 경우
            if (loginEmailEdittext.length() == 0 || loginPasswordEdittext.length() == 0 || loginNameEdittext.length() == 0) {
                Toast.makeText(this, getString(R.string.empty_info), Toast.LENGTH_SHORT).show()

            } else if (emailList.contains(loginEmailEdittext.text.toString()) && passwordList.contains(
                    loginPasswordEdittext.text.toString()
                ) && nameList.contains(loginNameEdittext.text.toString())
            ) {

                val intent = Intent(this, MainActivity::class.java)
                intent.putExtra("email", loginEmailEdittext.text.toString())
                intent.putExtra("name", loginNameEdittext.text.toString())
                startActivity(intent)

            } else {
                // 회원가입 정보에서 받은 데이터가 아닌 경우
                Toast.makeText(this, getString(R.string.notice_missinfo), Toast.LENGTH_SHORT).show()
            }

        }

        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }


        // 이메일 유효성 검사
        // signupEmailEdittext에 TextWatcher 연결
        loginEmailEdittext.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
            }
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // text가 바뀔 때마다 호출
                checkEmail()
            }
        })


        //비밀번호 유효성 검사
        loginPasswordEdittext.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                // 텍스트가 변경될 때마다 호출된다.
                // 비밀번호를 입력할 때 실시간으로 비밀번호 형식을 검사한다.
                isRegularPwd(loginPasswordEdittext)
            }
        })


    }

    fun checkEmail():Boolean {
        // 이메일 형식을 검사하는 정규식
        val emailValidation = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"
        val email = loginEmailEdittext.text.toString().trim()  //공백제거
        val p = Pattern.matches(emailValidation, email)       // emailValidation과 email이 서로 패턴이 맞는지 확인
        if (p) {
            // 이메일 형식이 올바를경우 -> 텍스트색상 black
            loginEmailEdittext.setTextColor(getColor(R.color.black))
            return true
        } else {
            // 이메일 형식이 올바르지 않을경우 -> 텍스트색상 red
            loginEmailEdittext.setTextColor(getColor(R.color.red))
            return false
        }
    }


    private fun isRegularPwd(editText: EditText):Boolean {
        val pwd = editText.text.toString().trim()
        val pwdPattern = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$@$!%*#?&.])[A-Za-z[0-9]$@$!%*#?&.]{8,16}$"
        val pattern = Pattern.matches(pwdPattern,pwd)
        if(pattern) {
            //유효성 검사 결과 정해진 비밀번호 형식일 경우
            editText.setTextColor(getColor(R.color.black))
            return true
        } else {
            // 유효성 검사 결과 비밀번호 형식이 아니면 EditText 테두리를 빨간색으로 처리한다.
            editText.setTextColor(getColor(R.color.red))
            return false
        }
    }
}

LoginActivity.kt

 

 

# LoginActivity 실행화면

 

 

 

 

# MainActivity에서 데이터받아오기

이제 MainActivtiy에서 데이터받아와서 프로필부분에도 데이터표시를 해주고, MyPageFragment에까지 데이터를 넘겨주는 작업을 해볼것이다

class MainActivity : AppCompatActivity() {

    lateinit var emailData : String
    lateinit var nameData : String
    lateinit var intentToLogin : Intent
    lateinit var profileBtn : ImageButton
    lateinit var profileTextview : TextView

    // companion object를 사용해서 바로 호출할 수 있도록
    companion object{
        lateinit var loginDataModel : LoginDataModel
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // LoginActivity에서 보낸 데이터 받아오기
        emailData = intent.getStringExtra("email") ?: getString(R.string.unknown)
        nameData = intent.getStringExtra("name") ?: getString(R.string.unknown)

        setContentView(R.layout.activity_main)

        profileBtn = findViewById(R.id.main_profile_imagebutton)
        profileTextview = findViewById(R.id.main_profile_textview)
        // profileTextview부분의 이름부분을 LoginActivity에서 받아온데이터로 사용
        profileTextview.text = getString(R.string.intro) + nameData + getString(R.string.nim)

        profileBtn.setOnClickListener {
            intentToLogin = Intent(this,FirstActivity::class.java)
            startActivity(intentToLogin)
        }

        BottomNavigation()

        // LoginDataModel에 받아온 emailData과 nameData을 넣어줌
        loginDataModel = LoginDataModel(emailData,nameData)
    }



    // bottomNavigation 구현함수
    private fun BottomNavigation(){


        val bottom_nav = findViewById<BottomNavigationView>(R.id.main_bottomnavgation)


        // main_framelayout레이아웃을 HomeFragment로 대체
        supportFragmentManager.beginTransaction()
            .replace(R.id.main_framelayout, HomeFragment())
            .commitAllowingStateLoss()


        bottom_nav.setOnItemSelectedListener { item ->

            when (item.itemId){

                // home클릭시 HomeFragment()로 대체
                R.id.home -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_framelayout, HomeFragment())
                        .commitAllowingStateLoss()
                    return@setOnItemSelectedListener true
                }

                // mypage클릭시 MypageFragment()로 대체
                R.id.mypage -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_framelayout, MypageFragment())
                        .commitAllowingStateLoss()

                    return@setOnItemSelectedListener true
                }

            }
            false
        }


    }

}

 

 

- MainActivtiy에서 데이터받아와서 프로필부분에 데이터표시해주기

email, name데이터를 받아와서 각각 emailData, nameData라는 변수에 넣어주고 (처음에는 초기값을 비회원으로 설정!)

프로필텍스트부분의 텍스트를 이름부분만 내가 작성한 이름으로 적용할 수 있게 nameData를 적용해준다. 나머지 부분은 string을 사용해서 표시해주도록 했다

- 실행화면

처음에는 초기값을 비회원으로 설정했기때문에 비회원으로 나오고, 로그인을 했을때 내가 작성한 이름으로 적용이 되는것을 확인할 수 있다

 

 

 

 

- MainActivity에서 받아온 데이터를 MyPageFragment에까지 데이터 넘겨주는 작업

(⭐️이부분 잘 몰라서 튜터님께 질문함. 기억 잘 해두기!)

 

Activity에서 Fragment로 데이터를 전달시켜줘야되는데 MainActivity안에 MypageFragment가 있어서 데이터를 어떻게 전달해야되는지 감이 안와서 튜터님께 물어봐서 해결을 했다!

 

먼저 데이터모델에 내가 전달할 데이터를 선언해줘야한다!!! 나는 이미 만들어놨던 데이터모델에 추가로 작성해줬다

data class DataModel (
    @DrawableRes
    val image : Int ,            // drawable은 숫자로 인식
    val title : String,          // 제목
    val content : String,        // 내용
    val nickName : String,       // 닉네임
    val profile_image : Int   // 프로필 이미지

)

// LoginDataModel 추가
data class LoginDataModel(
    val id : String,
    val name : String
)

DataModel.kt

이런식으로 LoginDataModel부분을 추가로 작성해줬고 MypageFragment에 id,name값만 뿌려줄거기때문에 이렇게 넣어줬다

 

class MainActivity : AppCompatActivity() {
   	...

    companion object{
        lateinit var loginDataModel : LoginDataModel
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
		...
        
        loginDataModel = LoginDataModel(emailData,nameData)
    }

MainActivity.kt

 

다시 MainActivtiy로 돌아와서 loginDataModel변수에 방금 만든 LoginDataModel을 선언해준다 (이걸 companion object로 묶어줘서 바로 호출할 수 있도록 해줌)

그리고 LoginDataModel에 받아온 emailData와 nameData를 넣어준다!!

 

이제 MypageFragment로 가서 MainActivtiy.loginDataModel.id와  MainActivtiy.loginDataModel.name을 사용해서 

MainActivtiy.loginDataModel의 id값과 name값을 가져와서 표시하고싶은 레이아웃에 이 값을 뿌려주면 끝이다!!

class MypageFragment : Fragment() {
    private lateinit var binding: FragmentMypageBinding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentMypageBinding.inflate(inflater,container,false)

        Log.d("LoginData", MainActivity.loginDataModel.toString())

	// MainActivity.loginDataModel의 id값을 가져옴
        val id = MainActivity.loginDataModel.id
        // MainActivity.loginDataModel의 name값을 가져옴
        val name = MainActivity.loginDataModel.name

	// 해당하는 레이아웃에 값 뿌려주기
        binding.mypageIdTextview2?.text = id
        binding.mypageNameTextview2?.text = name

        return binding.root
    }



}

 

# 실행화면

마이페이지에 내가 입력한 id값과 이름값이 잘 뜨는것을 확인해볼 수 있다

 

 

 

# MypageFragment에 스피너 구현하기

스피너 구현하기위해 먼저 아래와같이 파일 생성을 해준다

1.layout 폴더에 itme_spinner.xml파일 생성

2.values 폴더에 array.xml 파일 생성 (스피너에 들어갈 아이템 작성)

 

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tvItemSpinner"

    android:layout_width="match_parent"
    android:layout_height="45dp"

    android:paddingTop="10dp"
    android:paddingStart="30dp"
    android:textColor="@android:color/black"
    android:textSize="15sp"
    android:paddingLeft="30dp"/>

 itme_spinner.xml

 

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string-array name="itemList">
        <item>@string/no</item>
        <item>@string/bts</item>
        <item>@string/btob</item>
        <item>@string/idle</item>
    </string-array>

</resources>

array.xml

 

 

그다음 fragment_mypage에서 스피너와 스피너를 클릭했을때 보여줄 텍스트를 디자인해준다 (위에 레이아웃이 더 많이 있지만 보기편하게 생략함)

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main"
    android:background="@color/charcoal"
    android:layout_weight="1"
    tools:context=".MypageFragment">


	...
    

                <TextView
                    android:id="@+id/mypage_artist_textview2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:minHeight="25dp"
                    android:text="@string/btob"
                    android:textSize="20sp"
                    android:textColor="@color/black"
                    android:layout_marginStart="10dp"
                    app:layout_constraintBottom_toBottomOf="@+id/mypage_artist_textview"
                    app:layout_constraintStart_toEndOf="@+id/mypage_artist_textview"
                    app:layout_constraintTop_toTopOf="@+id/mypage_artist_textview" />

                <Spinner
                    android:id="@+id/mypage_spinner"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="5dp"
                    app:layout_constraintEnd_toEndOf="@+id/mypage_artist_textview2"
                    app:layout_constraintStart_toStartOf="@+id/mypage_artist_textview2"
                    app:layout_constraintTop_toBottomOf="@+id/mypage_artist_textview2" />



</androidx.constraintlayout.widget.ConstraintLayout>

fragment_mypage.xml

 

 

MypageFragment에서는 이런식으로 spinnerIdol()과 spinnerIdolResult()함수를 만들어서

spinnerIdol()함수에는 아까만든 array와 레이아웃을 불러와서, 스피너레이아웃과 어뎁터를 연결시켜주는 코드를 작성해준다

spinnerIdolResult()함수에는 스피너를 클릭했을때 표시될 텍스트뷰를 불러와서 연결해준다

class MypageFragment : Fragment() {
    private lateinit var binding: FragmentMypageBinding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentMypageBinding.inflate(inflater,container,false)

        Log.d("LoginData", MainActivity.loginDataModel.toString())

        val id = MainActivity.loginDataModel.id
        val name = MainActivity.loginDataModel.name

        binding.mypageIdTextview2?.text = id
        binding.mypageNameTextview2?.text = name

        spinnerIdol()
        spinnerIdolResult()

        return binding.root
    }


    // spinner의 값을 결정하는 함수
    fun spinnerIdol(){
        // itemList불러오기
        val idol = resources.getStringArray(R.array.itemList)
        // item_spinner를 어뎁터에 적용
        val Adapter = context?.let { ArrayAdapter(it, R.layout.item_spinner, idol) }

        // mypageSpinner와 어뎁터 연결
        binding.mypageSpinner?.adapter = Adapter
    }


    // 선택시 결과를 출력해주는 함수
    fun spinnerIdolResult(){

        binding.mypageSpinner?.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                // mypageArtistTextview2에 mypageSpinner에서 선택한값이 적용되도록
                binding.mypageArtistTextview2.text = "${binding.mypageSpinner?.getItemAtPosition(position)}"
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {
            }
        }
    }

}

MypageFragment.kt

 

# 스피너 실행화면

이런식으로 선택한 스피너의 아이템들이 텍스트뷰에 잘 표시가 된것을 확인할 수 있다

 

 

 

 

 

# 이메일, 비밀번호 유효성검사 / 스피너  참고자료

https://velog.io/@jinny_0422/Android-EditText%EC%9D%98-%EC%9D%B4%EB%A9%94%EC%9D%BC-%ED%98%95%EC%8B%9D-%EA%B2%80%EC%82%AC%ED%95%98%EA%B8%B0

 

[Android] TextWatcher를 사용한 Text 이메일 형식 검사하기

문의하기 화면을 구현한다고 가정한다! text를 입력할때 마다 이메일 형식에 맞는지 체크해주는 기능을 만들어 본다.

velog.io

 

https://developerson.tistory.com/82

 

Kotlin 안드로이드 화면에 Spinner 보이게 하기, Spinner로 선택한 항목 textView랑 연결하기

생성 파일 스피너를 만드는 두가지 방법 1.layout 폴더에 itme_spinner.xml파일 생성 2.values 폴더에 array.xml 파일 생성 1. item_spinner.xml 2. array.xml 과일선택 귤 파인애플 샤인머스캣 무화과 activity_main.xml act

developerson.tistory.com