Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Week2 #4

Merged
merged 31 commits into from
Apr 30, 2023
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
84733bb
feat : bottom navigation #3
SeonHwan-Kim Apr 17, 2023
7c9e9de
add : bottom navigation #3
SeonHwan-Kim Apr 17, 2023
853f1fa
add : home fragment #3
SeonHwan-Kim Apr 17, 2023
ae2707c
add : Gallery fragment #3
SeonHwan-Kim Apr 17, 2023
764d95d
add : search fragment #3
SeonHwan-Kim Apr 17, 2023
ce4c336
add : recyclerview:1.3.0 #3
SeonHwan-Kim Apr 18, 2023
730bff7
refactor : 파일 이동 #3
SeonHwan-Kim Apr 18, 2023
a9883b6
add : Dog data class 생성 #3
SeonHwan-Kim Apr 18, 2023
41e7b51
add : 강아지 이미지 추가 #3
SeonHwan-Kim Apr 19, 2023
d5049c0
add : title 추가 #3
SeonHwan-Kim Apr 19, 2023
48e7b68
feat : dog adapter 추가 #3
SeonHwan-Kim Apr 19, 2023
3336601
style : padding, layoutManager 추가 #3
SeonHwan-Kim Apr 19, 2023
b86fe26
feat : title, dog Adapter 연결 #3
SeonHwan-Kim Apr 19, 2023
817862d
add : 강아지 string 추가 #3
SeonHwan-Kim Apr 19, 2023
be68fa8
fix : 이미지 용량 줄이기 #3
SeonHwan-Kim Apr 20, 2023
4e6d0ae
fix : 이미지 용량 큰 값 삭제 #3
SeonHwan-Kim Apr 20, 2023
e73ca02
feat : scrollToTop 구현 #3
SeonHwan-Kim Apr 20, 2023
1a09339
feat : viewModel 사용 #3
SeonHwan-Kim Apr 20, 2023
79d4e4e
refactoring : 파일 분리 #3
SeonHwan-Kim Apr 21, 2023
4bc1873
add : add mypage #2
SeonHwan-Kim Apr 24, 2023
d1df01c
feat : mypage 하단바 추가 #2
SeonHwan-Kim Apr 24, 2023
d1be925
feat : 로그아웃, 회원탈퇴 구현 #2
SeonHwan-Kim Apr 25, 2023
7bb9b2b
feat : finishFragment 추가 #2
SeonHwan-Kim Apr 25, 2023
b8e1887
fix : startActivity 삭제 #2
SeonHwan-Kim Apr 25, 2023
c945074
add : sharedPreferences 분리 #2
SeonHwan-Kim Apr 26, 2023
fb4aa20
feat : SoptApplication 사용 #2
SeonHwan-Kim Apr 26, 2023
209a963
fix : DiffUtil과 ListAdapter 사용 #3
SeonHwan-Kim Apr 27, 2023
b49fb08
fix : applicationcontext this로 변경 #3
SeonHwan-Kim Apr 29, 2023
5027dac
fix : android ktx 사용 #3
SeonHwan-Kim Apr 29, 2023
314dc1d
fix : companion object 위치 수정 #3
SeonHwan-Kim Apr 30, 2023
a796a44
feat : mypage 이름, 특기 표시 #3
SeonHwan-Kim Apr 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

// ConcatAdapter
implementation "androidx.recyclerview:recyclerview:1.3.0"

// ViewModel 사용하기
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"

// ViewModel 생성함수를 편하게 사용하고 싶다면?
implementation "androidx.fragment:fragment-ktx:1.5.7"
implementation "androidx.activity:activity-ktx:1.7.1"
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">

<application
android:name=".SoptApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/org/android/go/sopt/SoptApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.android.go.sopt

import android.app.Application
import org.android.go.sopt.util.UserSharedPreferences

class SoptApplication : Application() {
companion object{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

companion object 는 kotlin 에서 주로 최하단에 위치합니다
(위에둬도 상관은 없지만..ㅎ)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 수정하겠습니다!

lateinit var prefs: UserSharedPreferences
}

override fun onCreate() {
prefs = UserSharedPreferences(this)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sharedPreferences 를 왜 사용하며, 앱 구동 및 종료시 메모리에서 어떻게 동작하는지,
왜 companion object (java static) 으로 구성하는지 를 공부해보면 좋겠네요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 한번 공부해보도록 하겠습니다!!!

super.onCreate()
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/org/android/go/sopt/data/Dog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.android.go.sopt.data

import androidx.annotation.DrawableRes

data class Dog(
val name: String,
@DrawableRes val image: Int,
val size: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@ 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.SoptApplication
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)
Expand All @@ -36,10 +34,15 @@ class LoginActivity : AppCompatActivity() {
private fun onClickLogin() {
with(binding) {
btMainLogin.setOnClickListener {
if (user !== null && user?.id == etMainId.text.toString() && user?.password == etMainPassword.text.toString()) {
if (SoptApplication.prefs.getString(
KEY_ID,
null
) == etMainId.text.toString() && SoptApplication.prefs.getString(
KEY_PASSWORD, null
) == etMainPassword.text.toString()
) {
val intent = Intent(this@LoginActivity, MainActivity::class.java)
intent.putExtra(IntentKey.USER_DATA, user)
saveUserInformation()
SoptApplication.prefs.setBoolean(KEY_ISLOGIN, true)
startActivity(intent)
showShortToast(getString(R.string.login_success_login_msg))
if (!isFinishing) finish()
Expand All @@ -50,13 +53,10 @@ class LoginActivity : AppCompatActivity() {
}
}


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))
}
}
Expand All @@ -68,39 +68,18 @@ class LoginActivity : AppCompatActivity() {
}
}

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, "")
)
if (SoptApplication.prefs.getBoolean(KEY_ISLOGIN, false)) {
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_ISLOGIN = "isLogin"
private const val KEY_ID = "id"
private const val KEY_PASSWORD = "password"
private const val KEY_NAME = "name"
private const val KEY_SPECIALTY = "specialty"
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
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
import org.android.go.sopt.presentation.main.gallery.GalleryFragment
import org.android.go.sopt.presentation.main.home.HomeFragment
import org.android.go.sopt.presentation.main.mypage.MyPageFragment
import org.android.go.sopt.presentation.main.search.SearchFragment


class MainActivity : AppCompatActivity() {
Expand All @@ -21,41 +18,54 @@ class MainActivity : AppCompatActivity() {
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()
this.initLayout()
this.goToTop()
}

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 initLayout() {
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 -> {
this.changeFragment(HomeFragment())
}
R.id.menu_search -> {
this.changeFragment(SearchFragment())
}
R.id.menu_gallery -> {
this.changeFragment(GalleryFragment())
}
else -> {
this.changeFragment(MyPageFragment())
}
}
return@setOnItemSelectedListener true
}
}


private fun changeFragment(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.replace(R.id.fcv_main, fragment)
.commit()
}

// private fun changeFragment(fragment: Fragment) {
// supportFragmentManager
// .beginTransaction()
// .replace(R.id.fcv_main, fragment)
// .commit()
// }
private fun goToTop(){
binding.bnvMain.setOnItemReselectedListener {
when(it.itemId){
R.id.menu_home -> {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fcv_main)
if(currentFragment is HomeFragment){
currentFragment.scrollToTop()
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.android.go.sopt.presentation.main.gallery

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import org.android.go.sopt.databinding.FragmentGalleryBinding

class GalleryFragment : Fragment() {
private var _binding: FragmentGalleryBinding? = null
private val binding: FragmentGalleryBinding
get() = requireNotNull(_binding) { "앗!_binding이 null이다!" }

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentGalleryBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}

override fun onDestroy() {
super.onDestroy()
_binding = null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.android.go.sopt.presentation.main.home

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import org.android.go.sopt.data.Dog
import org.android.go.sopt.databinding.ItemDogBinding

class DogAdapter(context: Context) : ListAdapter<Dog, DogAdapter.DogViewHolder>(DogDiffCallback()) {
private val inflater by lazy { LayoutInflater.from(context) }

class DogViewHolder(private val binding: ItemDogBinding) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(dog: Dog) {
binding.ivDogImage.setImageDrawable(binding.root.context.getDrawable(dog.image))
binding.tvDogName.text = dog.name
binding.tvDogSize.text = dog.size
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DogViewHolder {
val binding = ItemDogBinding.inflate(inflater, parent, false)
return DogViewHolder(binding)
}

override fun onBindViewHolder(holder: DogViewHolder, position: Int) {
holder.onBind(getItem(position))
}
}

class DogDiffCallback : DiffUtil.ItemCallback<Dog>() {
override fun areItemsTheSame(oldItem: Dog, newItem: Dog): Boolean {
return oldItem.name == newItem.name
}

override fun areContentsTheSame(oldItem: Dog, newItem: Dog): Boolean {
return oldItem == newItem
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.android.go.sopt.presentation.main.home

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ConcatAdapter
import org.android.go.sopt.databinding.FragmentHomeBinding

class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding: FragmentHomeBinding
get() = requireNotNull(_binding) { "앗!_binding이 null이다!" }

private val viewModel by viewModels<HomeViewModel>()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val titleAdapter = TitleAdapter(requireContext())
val dogAdapter = DogAdapter(requireContext())
dogAdapter.submitList(viewModel.mockDogList)
binding.rvHomeDog.adapter = ConcatAdapter(titleAdapter, dogAdapter)
}

override fun onDestroy() {
super.onDestroy()
_binding = null
}

fun scrollToTop() {
binding.rvHomeDog.smoothScrollToPosition(0)
}
}
Loading