diff --git a/app/build.gradle b/app/build.gradle index 2c92573..2ec3e92 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-parcelize' } android { @@ -37,7 +38,6 @@ android { } dependencies { - implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.11.0' @@ -45,4 +45,13 @@ dependencies { testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + + // recyclerview + implementation 'androidx.recyclerview:recyclerview:1.3.2' + + // ViewModel + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2" + + implementation "androidx.fragment:fragment-ktx:1.6.1" + implementation "androidx.activity:activity-ktx:1.8.0" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3be47f9..9cbbf81 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,6 +14,10 @@ tools:targetApi="31"> + + @@ -21,9 +25,6 @@ - diff --git a/app/src/main/java/com/sopt/now/LoginActivity.kt b/app/src/main/java/com/sopt/now/LoginActivity.kt index a53afaf..67ad22c 100644 --- a/app/src/main/java/com/sopt/now/LoginActivity.kt +++ b/app/src/main/java/com/sopt/now/LoginActivity.kt @@ -3,71 +3,85 @@ package com.sopt.now import android.content.Intent import android.os.Bundle import android.widget.Toast -import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import com.sopt.now.databinding.ActivityLoginBinding +import com.sopt.now.test.data.UserData +import com.sopt.now.test.data.UserPreference class LoginActivity : AppCompatActivity() { private lateinit var binding: ActivityLoginBinding - var userId = "" - var userPw = "" - var userName = "" - var userMbti = "" + private lateinit var signUpLauncher: ActivityResultLauncher + private lateinit var userPreference: UserPreference override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) + userPreference = UserPreference(this) + setSignUpLauncher() + setupLoginButton() + setupSignUpTextView() + } + + // 로그인 + private fun setupLoginButton() { binding.btnLogin.setOnClickListener { checkLogin() } + } - // 회원가입 페이지로 이동 + // 회원가입 페이지로 이동 + private fun setupSignUpTextView() { binding.tvSignUp.setOnClickListener { - val intent = Intent(this, SignUpActivity::class.java) - signUpLauncher.launch(intent) // ActivityResultLauncher 실행 + Intent(this, SignUpActivity::class.java).also { + signUpLauncher.launch(it) // ActivityResultLauncher 실행 + } } } - // ActivityResultLauncher 초기화 - private val signUpLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - handleSignUpResult(result) - } + // 로그인 + private fun checkLogin() { + val inputId = binding.etLoginId.text.toString() + val inputPw = binding.etLoginPw.text.toString() + val userData = userPreference.getUserData() - // 회원가입 결과 처리 - private fun handleSignUpResult(result: ActivityResult) { - when (result.resultCode) { - RESULT_OK -> { - userId = result.data!!.getStringExtra("userId").toString() - userPw = result.data!!.getStringExtra("userPw").toString() - userName = result.data!!.getStringExtra("userName").toString() - userMbti = result.data!!.getStringExtra("userMbti").toString() + // 아이디, 비번 확인 + if (userData != null) { + if (inputId == userData.userId && inputPw == userData.userPw) { + showToast("로그인 성공!") + moveToMain() + } else { + showToast("아이디 또는 비밀번호가 잘못되었습니다.") } } } - // 로그인 - private fun checkLogin(){ - var inputId = binding.etId.text.toString() - var inputPw = binding.etPw.text.toString() - - if(inputId == userId && inputPw == userPw){ - moveToMain(userId, userPw, userName, userMbti) + // 메인 페이지로 이동 + private fun moveToMain() { + Intent(this, MainActivity::class.java).apply { + startActivity(this) + finish() } } - // 메인 페이지로 이동 - private fun moveToMain(userId: String, userPw: String, userName: String, userMbti: String) { - val intent = Intent(this, MainActivity::class.java).apply { - putExtra("userId", userId) - putExtra("userPw", userPw) - putExtra("userName", userName) - putExtra("userMbti", userMbti) + // 사용자 데이터 저장 + private fun setSignUpLauncher(){ + signUpLauncher = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode == RESULT_OK) { + result.data?.getParcelableExtra("userData")?.let { + userPreference.saveUserData(it) + } + } } - startActivity(intent) - Toast.makeText(this, "로그인 성공!", Toast.LENGTH_SHORT).show() + } + + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/MainActivity.kt b/app/src/main/java/com/sopt/now/MainActivity.kt index 6a08aac..a9a899a 100644 --- a/app/src/main/java/com/sopt/now/MainActivity.kt +++ b/app/src/main/java/com/sopt/now/MainActivity.kt @@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.sopt.now.databinding.ActivityMainBinding import com.sopt.now.test.HomeFragment +import com.sopt.now.test.MyPageFragment import com.sopt.now.test.SearchFragment class MainActivity : AppCompatActivity() { @@ -25,8 +26,6 @@ class MainActivity : AppCompatActivity() { clickBottomNavigation() } - - private fun clickBottomNavigation() { binding.bnvHome.setOnItemSelectedListener{ when (it.itemId) { @@ -41,10 +40,9 @@ class MainActivity : AppCompatActivity() { } R.id.menu_mypage-> { - replaceFragment(SearchFragment()) + replaceFragment(MyPageFragment()) true } - else -> false } } @@ -55,4 +53,4 @@ class MainActivity : AppCompatActivity() { .replace(R.id.fcv_home, fragment) .commit() } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/SignUpActivity.kt b/app/src/main/java/com/sopt/now/SignUpActivity.kt index 83b6a15..ce07ce6 100644 --- a/app/src/main/java/com/sopt/now/SignUpActivity.kt +++ b/app/src/main/java/com/sopt/now/SignUpActivity.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.sopt.now.databinding.ActivitySignUpBinding +import com.sopt.now.test.data.UserData class SignUpActivity : AppCompatActivity() { @@ -15,46 +16,60 @@ class SignUpActivity : AppCompatActivity() { binding = ActivitySignUpBinding.inflate(layoutInflater) setContentView(binding.root) - // 회원 가입 + setupSignUpButton() + } + + // 회원 가입 + private fun setupSignUpButton() { binding.btnSignUp.setOnClickListener { - val userId = binding.etId.text.toString() - val userPw = binding.etPw.text.toString() - val userName = binding.etName.text.toString() - val userMbti = binding.etMbti.text.toString() + with(binding) { + val userId = etSignUpId.text.toString() + val userPw = etSignUpPw.text.toString() + val userName = etSignUpName.text.toString() + val selfDescription = etSignUpDescription.text.toString() - checkSignUp(userId, userPw, userName, userMbti) + val userData = UserData(userId, userPw, userName, selfDescription) + checkSignUp(userData) + } } } // 회원 가입 가능 여부 체크 - private fun checkSignUp(userId: String, userPw: String, userName: String, userMbti: String) { - val isValidId = userId.length in 6..10 - val isValidPw = userPw.length in 8..12 - val isValidName = userName.trim().isEmpty() // 공백으로만 이루어진 경우 판단 - val isEmpty = userId.isEmpty() || userId.isEmpty() || userId.isEmpty() || userMbti.isEmpty() + private fun checkSignUp(userData: UserData) { + val isValidId = userData.userId.length in MIN_ID_LENGTH..MAX_ID_LENGTH + val isValidPw = userData.userPw.length in MIN_PW_LENGTH..MAX_PW_LENGTH + val isValidName = userData.userName.isBlank() // 공백으로만 이루어진 경우 판단 val message = when { !isValidId -> "ID는 6~10 글자여야 합니다." !isValidPw -> "Password는 8~12 글자여야 합니다." isValidName -> "공백으로만 이루어진 닉네임은 불가합니다." - isEmpty -> "모든 정보를 입력해주세요." else -> { - moveToLogin(userId, userPw, userName, userMbti) + moveToLogin(userData) "회원가입 성공!" } } - Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + showToast(message) } // 로그인 페이지로 이동 - private fun moveToLogin(userId: String, userPw: String, userName: String, userMbti: String) { - val intent = Intent(this, LoginActivity::class.java).apply { - putExtra("userId", userId) - putExtra("userPw", userPw) - putExtra("userName", userName) - putExtra("userMbti", userMbti) + private fun moveToLogin(userData: UserData) { + Intent(this, LoginActivity::class.java).apply { + putExtra("userData", userData) + setResult(RESULT_OK, this) + finish() } - setResult(RESULT_OK, intent) - finish() + } + + private fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } + + // 글자 수 제한 + companion object { + private const val MIN_ID_LENGTH = 6 + private const val MAX_ID_LENGTH = 10 + private const val MIN_PW_LENGTH = 8 + private const val MAX_PW_LENGTH = 12 } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/HomeFragment.kt b/app/src/main/java/com/sopt/now/test/HomeFragment.kt index 5cd56a1..6d17d20 100644 --- a/app/src/main/java/com/sopt/now/test/HomeFragment.kt +++ b/app/src/main/java/com/sopt/now/test/HomeFragment.kt @@ -5,10 +5,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager import com.sopt.now.R import com.sopt.now.databinding.FragmentHomeBinding -import com.sopt.now.test.friend.Friend +import com.sopt.now.test.data.Friend +import com.sopt.now.test.data.HomeViewModel +import com.sopt.now.test.data.UserPreference import com.sopt.now.test.friend.FriendAdapter class HomeFragment: Fragment() { @@ -16,6 +19,9 @@ class HomeFragment: Fragment() { private val binding: FragmentHomeBinding get() = requireNotNull(_binding) { "바인딩 객체 좀 생성해주세요 제발!!" } + private val viewModel by viewModels() + private lateinit var userPreference: UserPreference + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -27,34 +33,38 @@ class HomeFragment: Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val friendAdapter = FriendAdapter() + + userPreference = UserPreference(requireContext()) + + setFriendList() + setRecyclerView() + } + + // 리스트에 사용자 정보 추가 + private fun setFriendList(){ + val userData = userPreference.getUserData() + + userData?.let { + val newFriend = Friend( + profileImage = R.drawable.iv_user_profile, + name = it.userName, + selfDescription = it.selfDescription + ) + viewModel.mockFriendList.add(0, newFriend) + } + } + + // FriendAdapter 연결 + private fun setRecyclerView(){ + val friendAdapter = FriendAdapter(viewModel.mockFriendList) binding.rvFriends.run { - adapter = friendAdapter layoutManager = LinearLayoutManager(requireContext()) + setAdapter(friendAdapter) } - friendAdapter.setFriendList(mockFriendList) } override fun onDestroyView() { super.onDestroyView() _binding = null } - - private val mockFriendList = listOf( - Friend( - profileImage = R.drawable.img_profile, - name = "이의경", - selfDescription = "ㅎㅎ 아직 반도 안왔어 ^&^", - ), - Friend( - profileImage = R.drawable.img_profile, - name = "우상욱", - selfDescription = "나보다 안드 잘하는 사람 있으면 나와봐", - ), - Friend( - profileImage = R.drawable.img_profile, - name = "배지현", - selfDescription = "표정 풀자 ^^", - ), - ) -} +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/MyPageFragment.kt b/app/src/main/java/com/sopt/now/test/MyPageFragment.kt index d12966f..c3b8d53 100644 --- a/app/src/main/java/com/sopt/now/test/MyPageFragment.kt +++ b/app/src/main/java/com/sopt/now/test/MyPageFragment.kt @@ -6,12 +6,15 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.sopt.now.databinding.FragmentMypageBinding +import com.sopt.now.test.data.UserPreference -class MyPageFragment: Fragment() { +class MyPageFragment : Fragment() { private var _binding: FragmentMypageBinding? = null private val binding: FragmentMypageBinding get() = requireNotNull(_binding) { "바인딩 객체 좀 생성해주세요 제발!!" } + private lateinit var userPreference: UserPreference + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -23,11 +26,25 @@ class MyPageFragment: Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - // 기존 액티비티의 onCreate에 작성했던 init로직을 이제는 여기에 작성합니다. + userPreference = UserPreference(requireContext()) + setupUserData() + } + + // 받아온 UserData 적용 + private fun setupUserData() { + val userData = userPreference.getUserData() + if (userData != null) { + with(binding) { + tvMyName.text = userData.userName + tvMyDescription.text = userData.selfDescription + tvMyId.text = userData.userId + tvMyPw.text = userData.userPw + } + } } override fun onDestroyView() { super.onDestroyView() _binding = null } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/friend/Friend.kt b/app/src/main/java/com/sopt/now/test/data/Friend.kt similarity index 54% rename from app/src/main/java/com/sopt/now/test/friend/Friend.kt rename to app/src/main/java/com/sopt/now/test/data/Friend.kt index 4913d67..d8cff03 100644 --- a/app/src/main/java/com/sopt/now/test/friend/Friend.kt +++ b/app/src/main/java/com/sopt/now/test/data/Friend.kt @@ -1,4 +1,4 @@ -package com.sopt.now.test.friend +package com.sopt.now.test.data import androidx.annotation.DrawableRes @@ -6,4 +6,9 @@ data class Friend( @DrawableRes val profileImage: Int, val name: String, val selfDescription: String, -) +) { + companion object { + const val TYPE_USER = 0 + const val TYPE_FRIEND = 1 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/data/HomeViewModel.kt b/app/src/main/java/com/sopt/now/test/data/HomeViewModel.kt new file mode 100644 index 0000000..39663b2 --- /dev/null +++ b/app/src/main/java/com/sopt/now/test/data/HomeViewModel.kt @@ -0,0 +1,59 @@ +package com.sopt.now.test.data + +import androidx.lifecycle.ViewModel +import com.sopt.now.R + +class HomeViewModel() : ViewModel() { + val mockFriendList = mutableListOf( + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "AAA", + selfDescription = "AAA님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "BBB", + selfDescription = "BBB님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "CCC", + selfDescription = "CCC님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "DDD", + selfDescription = "DDD님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "EEE", + selfDescription = "EEE님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "FFF", + selfDescription = "FFF님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "GGG", + selfDescription = "GGG님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "HHH", + selfDescription = "HHH님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "III", + selfDescription = "III님의 한 줄 소개", + ), + Friend( + profileImage = R.drawable.iv_friend_profile, + name = "JJJ", + selfDescription = "JJJ님의 한 줄 소개", + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/data/UserData.kt b/app/src/main/java/com/sopt/now/test/data/UserData.kt new file mode 100644 index 0000000..159a145 --- /dev/null +++ b/app/src/main/java/com/sopt/now/test/data/UserData.kt @@ -0,0 +1,12 @@ +package com.sopt.now.test.data + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class UserData( + val userId: String, + val userPw: String, + val userName: String, + val selfDescription: String +): Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/data/UserPreference.kt b/app/src/main/java/com/sopt/now/test/data/UserPreference.kt new file mode 100644 index 0000000..2c562ca --- /dev/null +++ b/app/src/main/java/com/sopt/now/test/data/UserPreference.kt @@ -0,0 +1,34 @@ +package com.sopt.now.test.data + +import android.content.Context + +class UserPreference(context: Context) { + private val sharedPreferences = context.getSharedPreferences("userData", Context.MODE_PRIVATE) + + // 사용자 데이터 저장 + fun saveUserData(userData: UserData) { + with(sharedPreferences.edit()){ + putString("userId", userData.userId) + putString("userPw", userData.userPw) + putString("userName", userData.userName) + putString("selfDescription", userData.selfDescription) + apply() + } + } + + // 사용자 데이터 가져오기 + fun getUserData(): UserData? { + with(sharedPreferences){ + val userId = getString("userId", null) + val userPw = getString("userPw", null) + val userName = getString("userName", null) + val selfDescription = getString("selfDescription", null) + + return if (userId != null && userPw != null && userName != null && selfDescription != null) { + UserData(userId, userPw, userName, selfDescription) + } else { + null + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/friend/FriendAdapter.kt b/app/src/main/java/com/sopt/now/test/friend/FriendAdapter.kt index 7056e1e..d3fc245 100644 --- a/app/src/main/java/com/sopt/now/test/friend/FriendAdapter.kt +++ b/app/src/main/java/com/sopt/now/test/friend/FriendAdapter.kt @@ -4,25 +4,47 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.sopt.now.databinding.ItemFriendBinding +import com.sopt.now.databinding.ItemUserBinding +import com.sopt.now.test.data.Friend -class FriendAdapter() : RecyclerView.Adapter() { - // 임시의 빈 리스트 - private var friendList: List = emptyList() +class FriendAdapter(private val profiles: List) : RecyclerView.Adapter() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendViewHolder { - val inflater = LayoutInflater.from(parent.context) - val binding = ItemFriendBinding.inflate(inflater, parent, false) - return FriendViewHolder(binding) - } + // 첫 번째 아이템 + private val FIRST_ITEM_POSITION = 0 - override fun onBindViewHolder(holder: FriendViewHolder, position: Int) { - holder.onBind(friendList[position]) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { + return when (viewType) { + Friend.TYPE_USER -> { + val binding = ItemUserBinding.inflate(LayoutInflater.from(parent.context), parent, false) + UserViewHolder(binding) + } + Friend.TYPE_FRIEND -> { + val binding = ItemFriendBinding.inflate(LayoutInflater.from(parent.context), parent, false) + FriendViewHolder(binding) + } + else -> throw IllegalArgumentException("Invalid view type") + } } - override fun getItemCount() = friendList.size + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + val profile = profiles[position] + + when (holder) { + is FriendViewHolder -> { + holder.onBind(profile) + } + is UserViewHolder -> { + holder.onBind(profile) + } + } + } - fun setFriendList(friendList: List) { - this.friendList = friendList.toList() - notifyDataSetChanged() // 권장하지 않음 (비효율) + override fun getItemViewType(position: Int): Int { + return when (position) { + FIRST_ITEM_POSITION -> Friend.TYPE_USER + else -> Friend.TYPE_FRIEND + } } + + override fun getItemCount(): Int = profiles.size } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/test/friend/FriendViewHolder.kt b/app/src/main/java/com/sopt/now/test/friend/FriendViewHolder.kt index 596c012..a4c50fc 100644 --- a/app/src/main/java/com/sopt/now/test/friend/FriendViewHolder.kt +++ b/app/src/main/java/com/sopt/now/test/friend/FriendViewHolder.kt @@ -1,14 +1,29 @@ package com.sopt.now.test.friend import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding import com.sopt.now.databinding.ItemFriendBinding +import com.sopt.now.databinding.ItemUserBinding +import com.sopt.now.test.data.Friend -class FriendViewHolder(private val binding: ItemFriendBinding) : RecyclerView.ViewHolder(binding.root) { +sealed class BaseViewHolder(binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) + +class FriendViewHolder(private val binding: ItemFriendBinding) : BaseViewHolder(binding) { fun onBind(friendData: Friend) { binding.run { - ivProfile.setImageResource(friendData.profileImage) - tvName.text = friendData.name - tvSelfDescription.text = friendData.selfDescription + ivFriendProfile.setImageResource(friendData.profileImage) + tvFriendName.text = friendData.name + tvFriendDescription.text = friendData.selfDescription + } + } +} + +class UserViewHolder(private val binding: ItemUserBinding) : BaseViewHolder(binding) { + fun onBind(userData: Friend) { + binding.run { + ivMyProfile.setImageResource(userData.profileImage) + tvMyName.text = userData.name + tvMyDescription.text = userData.selfDescription } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_search_white_24.xml b/app/src/main/res/drawable/ic_search_white_24.xml new file mode 100644 index 0000000..594dd56 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_white_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/iv_friend_profile.jpg b/app/src/main/res/drawable/iv_friend_profile.jpg new file mode 100644 index 0000000..212e30a Binary files /dev/null and b/app/src/main/res/drawable/iv_friend_profile.jpg differ diff --git a/app/src/main/res/drawable/img_profile.jpg b/app/src/main/res/drawable/iv_user_profile.jpg similarity index 100% rename from app/src/main/res/drawable/img_profile.jpg rename to app/src/main/res/drawable/iv_user_profile.jpg diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 1e4eff3..e7ad30c 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -10,7 +10,7 @@ tools:context=".LoginActivity"> + app:layout_constraintTop_toBottomOf="@+id/tv_login_title"/> + app:layout_constraintTop_toBottomOf="@+id/tv_login_id"/> + app:layout_constraintTop_toBottomOf="@+id/et_login_id"/> + app:layout_constraintTop_toBottomOf="@+id/tv_login_pw"/>