diff --git a/app/build.gradle b/app/build.gradle index 2b912e8..749a2cb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,20 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'kotlin-parcelize' } android { namespace 'org.android.go.sopt' compileSdk 33 + buildFeatures { + viewBinding = true + } + defaultConfig { applicationId "org.android.go.sopt" - minSdk 28 + minSdk 24 targetSdk 32 versionCode 1 versionName "1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 49ec931..fcec636 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,14 +12,24 @@ android:theme="@style/Theme.GOSOPTAndroid" tools:targetApi="31"> + android:name=".presentation.signup.SignUpActivity" + android:exported="false" + android:screenOrientation="portrait"/> + + \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/MainActivity.kt b/app/src/main/java/org/android/go/sopt/MainActivity.kt deleted file mode 100644 index a2ef57d..0000000 --- a/app/src/main/java/org/android/go/sopt/MainActivity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.android.go.sopt - -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/data/User.kt b/app/src/main/java/org/android/go/sopt/data/User.kt new file mode 100644 index 0000000..0264b4c --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/data/User.kt @@ -0,0 +1,12 @@ +package org.android.go.sopt.data + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class User( + val id: String? = "", + val password: String? = "", + val name: String? = "", + val specialty: String? = "", +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/presentation/login/LoginActivity.kt b/app/src/main/java/org/android/go/sopt/presentation/login/LoginActivity.kt new file mode 100644 index 0000000..627a575 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/presentation/login/LoginActivity.kt @@ -0,0 +1,106 @@ +package org.android.go.sopt.presentation.login + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import androidx.activity.result.ActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import org.android.go.sopt.R +import org.android.go.sopt.data.User +import org.android.go.sopt.presentation.main.MainActivity +import org.android.go.sopt.presentation.signup.SignUpActivity +import org.android.go.sopt.databinding.ActivityLoginBinding +import org.android.go.sopt.util.* + + +class LoginActivity : AppCompatActivity() { + + private lateinit var binding: ActivityLoginBinding + private var user: User? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityLoginBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.root.setOnClickListener { + hideKeyboard(binding.root) + } + + this.autoLogin() + this.onClickLogin() + this.onCLickSignUp() + } + + private fun onClickLogin() { + with(binding) { + btMainLogin.setOnClickListener { + if (user !== null && user?.id == etMainId.text.toString() && user?.password == etMainPassword.text.toString()) { + val intent = Intent(this@LoginActivity, MainActivity::class.java) + intent.putExtra(IntentKey.USER_DATA, user) + saveUserInformation() + startActivity(intent) + showShortToast(getString(R.string.login_success_login_msg)) + if (!isFinishing) finish() + } else { + showShortToast(getString(R.string.login_fail_login_msg)) + } + } + } + } + + + private val getResultSignUp = registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result: ActivityResult -> + if (result.resultCode == RESULT_OK) { + user = result.data?.getParcelable(IntentKey.USER_DATA, User::class.java) + Log.d("user", "---------\n$user") + showShortSnackbar(binding.root, getString(R.string.login_success_sign_up_msg)) + } + } + + private fun onCLickSignUp() { + binding.btMainSignUp.setOnClickListener { + val intent = Intent(this, SignUpActivity::class.java) + getResultSignUp.launch(intent) + } + } + + private fun saveUserInformation() { + val sharedPreference = getSharedPreferences(KEY_PREFS, 0) + val editor = sharedPreference.edit() + editor.putString(KEY_ID, user?.id) + editor.putString(KEY_PASSWORD, user?.password) + editor.putString(KEY_NAME, user?.name) + editor.putString(KEY_SPECIALTY, user?.specialty) + editor.apply() + } + + private fun autoLogin() { + val sharedPreferences = getSharedPreferences(KEY_PREFS, 0) + + if (sharedPreferences.contains(KEY_ID) || sharedPreferences.contains(KEY_PASSWORD)) { + user = User( + sharedPreferences.getString(KEY_ID, ""), + sharedPreferences.getString(KEY_PASSWORD, ""), + sharedPreferences.getString(KEY_NAME, ""), + sharedPreferences.getString(KEY_SPECIALTY, "") + ) + val intent = Intent(this, MainActivity::class.java) + intent.putExtra(IntentKey.USER_DATA, user) + startActivity(intent) + showShortToast(getString(R.string.login_success_login_msg)) + if (!isFinishing) finish() + } + } + + companion object { + private const val KEY_PREFS = "autoLogin" + private const val KEY_ID = "id" + private const val KEY_PASSWORD = "password" + private const val KEY_NAME = "name" + private const val KEY_SPECIALTY = "specialty" + } +} diff --git a/app/src/main/java/org/android/go/sopt/presentation/main/MainActivity.kt b/app/src/main/java/org/android/go/sopt/presentation/main/MainActivity.kt new file mode 100644 index 0000000..4ccb2e1 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/presentation/main/MainActivity.kt @@ -0,0 +1,61 @@ +package org.android.go.sopt.presentation.main + +import android.os.Build +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import androidx.fragment.app.Fragment +import org.android.go.sopt.GalleryFragment +import org.android.go.sopt.HomeFragment +import org.android.go.sopt.R +import org.android.go.sopt.SearchFragment +import org.android.go.sopt.data.User +import org.android.go.sopt.databinding.ActivityMainBinding +import org.android.go.sopt.util.IntentKey +import org.android.go.sopt.util.getParcelable + + +class MainActivity : AppCompatActivity() { + private lateinit var binding: ActivityMainBinding + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + +// val currentFragment = supportFragmentManager.findFragmentById(R.id.fcv_main) +// if (currentFragment == null) { +// supportFragmentManager.beginTransaction().add(R.id.fcv_main, HomeFragment()).commit() +// } +// binding.bnvMain.setOnItemSelectedListener { item -> +// when (item.itemId) { +// R.id.menu_home -> { +// HomeFragment() +// return@setOnItemSelectedListener true +// } +// R.id.menu_search -> { +// SearchFragment() +// return@setOnItemSelectedListener true +// } +// else -> { +// GalleryFragment() +// return@setOnItemSelectedListener true +// +// } +// } +// } + + this.getUserData() + } + + private fun getUserData() { + val user: User? = intent.getParcelable(IntentKey.USER_DATA, User::class.java) + binding.tvMainName.text = "이름 : ${user?.name}" + binding.tvMainSpecialty.text = "특기 : ${user?.specialty}" + } + +// private fun changeFragment(fragment: Fragment) { +// supportFragmentManager +// .beginTransaction() +// .replace(R.id.fcv_main, fragment) +// .commit() +// } +} \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/presentation/signup/SignUpActivity.kt b/app/src/main/java/org/android/go/sopt/presentation/signup/SignUpActivity.kt new file mode 100644 index 0000000..13ec7c3 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/presentation/signup/SignUpActivity.kt @@ -0,0 +1,63 @@ +package org.android.go.sopt.presentation.signup + +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import org.android.go.sopt.R +import org.android.go.sopt.data.User +import org.android.go.sopt.databinding.ActivitySignUpBinding +import org.android.go.sopt.presentation.login.LoginActivity +import org.android.go.sopt.util.IntentKey +import org.android.go.sopt.util.hideKeyboard +import org.android.go.sopt.util.showShortToast + +class SignUpActivity : AppCompatActivity() { + + private lateinit var binding: ActivitySignUpBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivitySignUpBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.root.setOnClickListener { + hideKeyboard(binding.root) + } + + this.onClickComplete() + } + + private fun onClickComplete() { + with(binding) { + btSignupComplete.setOnClickListener { + val id = etSignupId.text + val password = etSignupPassword.text + val name = etSignupName.text + val specialty = etSignupSpecialty.text + + if (id.length !in 6..10) { + showShortToast(getString(R.string.sign_up_id_err_msg)) + } else if (password.length !in 8..12) { + showShortToast(getString(R.string.sign_up_password_err_msg)) + } else if (name.isEmpty()) { + showShortToast(getString(R.string.sign_up_name_err_msg)) + } else if (specialty.isEmpty()) { + showShortToast(getString(R.string.sign_up_specialty_err_msg)) + } else { + val intent = Intent(this@SignUpActivity, LoginActivity::class.java) + intent.putExtra( + IntentKey.USER_DATA, User( + id.toString(), + password.toString(), + name.toString(), + specialty.toString() + ) + ) + setResult(RESULT_OK, intent) + // 만약 종료가 되지 않았다면 종료시키기 + if (!isFinishing) finish() + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/util/ContextExtension.kt b/app/src/main/java/org/android/go/sopt/util/ContextExtension.kt new file mode 100644 index 0000000..41e7cf5 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/util/ContextExtension.kt @@ -0,0 +1,22 @@ +package org.android.go.sopt.util + +import android.content.Context +import android.view.View +import android.view.inputmethod.InputMethodManager +import android.widget.Toast +import com.google.android.material.snackbar.Snackbar + +fun Context.showShortToast(message: String){ + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() +} + +fun Context.hideKeyboard(view: View){ + val inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + // hideSoftInputFromWindow는 첫번째 인자로 windowToken을 받아야함. windowToken은 View에서 사용? + inputManager.hideSoftInputFromWindow(view.windowToken, 0) +} + +fun Context.showShortSnackbar(view: View, message: String){ + // Snackbar.make는 첫번째 인자로 View를 받아야한다. 그래서 this(context)를 쓰면 에러남 + Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show() +} \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/util/IntentExtension.kt b/app/src/main/java/org/android/go/sopt/util/IntentExtension.kt new file mode 100644 index 0000000..cf495f5 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/util/IntentExtension.kt @@ -0,0 +1,11 @@ +package org.android.go.sopt.util + +import android.content.Intent +import android.os.Build.VERSION.SDK_INT +import android.os.Build.VERSION_CODES.TIRAMISU +import android.os.Parcelable + +fun Intent.getParcelable(key: String, clazz: Class): T? = when { + SDK_INT >= TIRAMISU -> getParcelableExtra(key, clazz) + else -> getParcelableExtra(key) as? T +} \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/util/IntentKey.kt b/app/src/main/java/org/android/go/sopt/util/IntentKey.kt new file mode 100644 index 0000000..9d90054 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/util/IntentKey.kt @@ -0,0 +1,5 @@ +package org.android.go.sopt.util + +object IntentKey { + const val USER_DATA = "USER_DATA" +} \ No newline at end of file diff --git a/app/src/main/java/org/android/go/sopt/util/ViewExtension.kt b/app/src/main/java/org/android/go/sopt/util/ViewExtension.kt new file mode 100644 index 0000000..2a798e3 --- /dev/null +++ b/app/src/main/java/org/android/go/sopt/util/ViewExtension.kt @@ -0,0 +1,9 @@ +package org.android.go.sopt.util + +import android.view.View +import com.google.android.material.snackbar.Snackbar + +// View 객체를 상속받는 곳에서만 사용 가능~ +//fun View.showShortSnackBar(message: String){ +// Snackbar.make(this, message, Snackbar.LENGTH_SHORT).show() +//} diff --git a/app/src/main/res/drawable/img_introduce.jpg b/app/src/main/res/drawable/img_introduce.jpg new file mode 100644 index 0000000..ab58038 Binary files /dev/null and b/app/src/main/res/drawable/img_introduce.jpg differ diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..41f3b3f --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + +