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

경북대_Android_이혜원 1주차 과제 #3

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,44 @@
# android-contacts

Step1 : 연락처 추가

[제시된 기능요구사항]

[목표]
: 간단한 연락처를 구현한다.
* 연락처를 추가한다.
* 이름과 전화번호는 필수 값이다.
* 입력하지 않으면 토스트 메시지를 보여준다.
* 전화번호 입력은 숫자만 가능하다.
* 더보기를 눌러 입력 폼을 확장할 수 있다.
* 생일, 성별, 메모 입력 폼이 등장한다.
* 성별을 둘 중 하나를 선택할 수 있다.
* 저장 버튼을 누르면 '저장이 완료 되었습니다' 라는 토스트 메시지를 보여준다.
* 취소 버튼을 누르면 '취소 되었습니다' 라는 토스트 메시지를 보여준다.

[나누어진 커밋 단계]
1. doc : ReadMe 파일 추가
2. feat : 레이아웃 추가 (UI추가)
3. feat : 이름과 전화번호를 입력하지 않을시 토스트 메시지 보내기 구현
4. feat :더보기를 누를시, 입력폼 확장 구현
5. feat : 이름과 전화번호를 누를시, ‘저장완료’ 토스트 메시지 보내기 구현
6. feat : 취소 버튼을 누를시, ‘취소완료’ 토스트 메시지 보내기 구현


Step2 : 연락처 목록

[제시된 기능 요구 사항]
목표 : 간단한 연락처를 구현한다.

연락처 등록 화면을 구현한다.
연락처를 저장하면 목록에 추가된다.
저장된 연락처가 많을 경우 목록은 스크롤 되어야 한다.
추가된 연락처를 선택하여 상세 화면을 볼 수 있다.
연락처 작성 중 뒤로가기 버튼을 누르면 확인 팝업이 나타난다.
추가된 연락처는 앱을 다시 실행하면 유지되지 않는다.

1. 연락처 등록 화면 구현
2. 연락처 저장시, 목록에 추가 기능 구현
3. 목록 화면 구현
4. 연락처 목록에서 상세페이지 화면 구현
5. 상세페이지 보기 기능 구현
18 changes: 16 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.storage.CacheResetOnProcessCanceled.enabled

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
Expand All @@ -22,7 +24,7 @@ android {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
"proguard-rules.pro"
)
}
}
Expand All @@ -33,15 +35,27 @@ android {
kotlinOptions {
jvmTarget = "17"
}

buildFeatures {
viewBinding = true
dataBinding = true
Comment on lines +40 to +41
Copy link

Choose a reason for hiding this comment

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

두개의 차이는 무엇이며, 두개를 왜 꼭 같이 써야할까요~?

}
}

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")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.activity:activity:1.8.0")
implementation("androidx.databinding:databinding-runtime:8.5.0")

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation("androidx.fragment:fragment-ktx:1.6.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")



}
11 changes: 10 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,17 @@
android:supportsRtl="true"
android:theme="@style/Theme.Contacts"
tools:targetApi="31">
<activity
android:name=".DetailContact"
android:exported="false" />
<activity
android:name=".ListActivity"
android:exported="true"></activity>
<activity
android:name=".MainActivity"
android:exported="true" />
<activity
android:name=".PlusActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand All @@ -23,4 +32,4 @@
</activity>
</application>

</manifest>
</manifest>
17 changes: 17 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/ContactViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package campus.tech.kakao.contacts

import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class ContactViewModel : ViewModel() {
val contactListLiveData = MutableLiveData<MutableList<contact>>().apply {
value = ContactList
}

fun addContact(contact: contact) {
ContactList.add(contact)
contactListLiveData.value = ContactList
Log.d("ContactViewModel", "Contact added: ${contact.name}, total contacts: ${ContactList.size}")
}
}
Comment on lines +7 to +17
Copy link

Choose a reason for hiding this comment

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

MVVM은 안쓰기로 하지 않았나요~?

22 changes: 22 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/DetailContact.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package campus.tech.kakao.contacts

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import campus.tech.kakao.contacts.databinding.ActivityDetailContactBinding

class DetailContact : AppCompatActivity() {
private lateinit var binding: ActivityDetailContactBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailContactBinding.inflate(layoutInflater)
setContentView(binding.root)

// Intent로부터 데이터를 받아와서 UI에 설정
val name = intent.getStringExtra("name")
Copy link

Choose a reason for hiding this comment

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

보통 이런 요소는 Constant라는 object를 파일단위로 생성하고
const val NAV_KEY_NAME= name" 을 변수로 세팅하여 사용합니다.
그리고 받는쪽에서도 이것을 사용하는거죠.

val phoneNumber = intent.getStringExtra("phoneNumber")

binding.Name.text = name
binding.TelePhone.text = phoneNumber
}
}
57 changes: 57 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/ListActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package campus.tech.kakao.contacts

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.ImageButton
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import campus.tech.kakao.contacts.databinding.ActivityListBinding

class ListActivity : AppCompatActivity() {
private lateinit var binding: ActivityListBinding
private val contactViewModel: ContactViewModel by viewModels()
private lateinit var adapter: ListViewAdapter

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

binding = DataBindingUtil.setContentView(this, R.layout.activity_list)
val plusButton: ImageButton = findViewById(R.id.PlusButton)

initListView()

plusButton.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}

override fun onResume() {
super.onResume()
handleIncomingIntent()
}

private fun initListView() {
adapter = ListViewAdapter()
binding.listView.adapter = adapter

contactViewModel.contactListLiveData.observe(this) { contactList ->
adapter.notifyDataSetChanged()
}
}

private fun handleIncomingIntent() {
val name = intent.getStringExtra("name") ?: ""
val phoneNumber = intent.getStringExtra("phoneNumber") ?: ""

if (name.isNotEmpty() && phoneNumber.isNotEmpty()) {
Log.d("ListActivity", "New contact: $name, $phoneNumber")
Copy link

Choose a reason for hiding this comment

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

코드를 업로드하기전엔 로그를 되도록 지워주세요.

contactViewModel.addContact(contact(name, name[0].toString(), phoneNumber))
// Intent 데이터를 초기화하여 중복 추가 방지
intent.removeExtra("name")
intent.removeExtra("phoneNumber")
}
}
}
48 changes: 48 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/ListViewAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package campus.tech.kakao.contacts

import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import campus.tech.kakao.contacts.databinding.ContactListBarBinding

class ListViewAdapter : BaseAdapter() {

override fun getCount(): Int = ContactList.size

override fun getItem(position: Int): contact = ContactList[position]

override fun getItemId(position: Int): Long = position.toLong()

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val binding: ContactListBarBinding
val view: View

if (convertView == null) {
binding = ContactListBarBinding.inflate(LayoutInflater.from(parent.context), parent, false)
view = binding.root
view.tag = binding
} else {
binding = convertView.tag as ContactListBarBinding
view = convertView
}

val contact = getItem(position)
binding.NameSpace.text = contact.name
binding.OneNameSpace.text = contact.oneName
binding.TeleSpace.text = contact.phone_number

// 아이템 클릭 리스너 설정
view.setOnClickListener {
val context = parent.context
val intent = Intent(context, DetailContact::class.java).apply {
putExtra("name", contact.name)
putExtra("phoneNumber", contact.phone_number)
}
context.startActivity(intent)
}

return view
}
}
60 changes: 60 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,71 @@
package campus.tech.kakao.contacts

import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.LinearLayoutCompat

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val nameEdit: EditText = findViewById(R.id.NameEdit)
val phoneNumberEdit: EditText = findViewById(R.id.PhoneNumberEdit)
val moreText: TextView = findViewById(R.id.MoreText)
val birthEdit: EditText = findViewById(R.id.BirthEdit)
val memoEdit: EditText = findViewById(R.id.MemoEdit)
val genderArea: LinearLayoutCompat = findViewById(R.id.GenderArea)
val saveText: TextView = findViewById(R.id.SaveText)
val cancelText: TextView = findViewById(R.id.CancleText)
Comment on lines +19 to +26
Copy link

Choose a reason for hiding this comment

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

메소드를 실행시킬때마다 비싼 xml 파싱을 통해 뷰를 탐색해내는 findViewBy 를 실행하는 것이 아닌,
액티비티가 열렸을때 one-time만 이것들을 호출하여 필드 인스턴스를 할당하고 그것을 계속 재사용하는게 성능측면에서 더 좋아보입니다.


moreText.setOnClickListener {
moreText.visibility = View.GONE
birthEdit.visibility = View.VISIBLE
memoEdit.visibility = View.VISIBLE
genderArea.visibility = View.VISIBLE
}

saveText.setOnClickListener {
val name = nameEdit.text.toString().trim()
val phoneNumber = phoneNumberEdit.text.toString().trim()

if (name.isEmpty()) {
Toast.makeText(this@MainActivity, "이름은 필수값입니다.", Toast.LENGTH_SHORT).show()
Copy link

Choose a reason for hiding this comment

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

이런 String은 strings.xml에서 관리하는게 좋아보입니다.

} else if (phoneNumber.isEmpty()) {
Toast.makeText(this@MainActivity, "전화번호는 필수값입니다.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this@MainActivity, "저장되었습니다.", Toast.LENGTH_SHORT).show()

val intent = Intent(this, ListActivity::class.java).apply {
putExtra("name", name)
putExtra("phoneNumber", phoneNumber)
}
startActivity(intent)
finish()
Comment on lines +46 to +51
Copy link

Choose a reason for hiding this comment

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

navigateToContactListView() 이런 함수로 감싸는것도 좋아보이네요.

}
}

cancelText.setOnClickListener {
Toast.makeText(this@MainActivity, "취소되었습니다.", Toast.LENGTH_SHORT).show()
finish()
}
}

override fun onBackPressed() {
// 확인 다이얼로그 표시
AlertDialog.Builder(this)
.setMessage("작성을 취소하시겠습니까?")
.setPositiveButton("예") { dialog, which ->
super.onBackPressed()
}
.setNegativeButton("아니오", null)
.show()
}
}
22 changes: 22 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/PlusActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package campus.tech.kakao.contacts

import android.content.Intent
import android.os.Bundle
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity

class PlusActivity : AppCompatActivity() {

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

var PlusButton : ImageButton = findViewById(R.id.PlusButton)

val intent = Intent(this,MainActivity::class.java)
PlusButton.setOnClickListener{
startActivity(intent)
}

}
}
9 changes: 9 additions & 0 deletions app/src/main/java/campus/tech/kakao/contacts/contact.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package campus.tech.kakao.contacts

var ContactList: MutableList<contact> = mutableListOf()

data class contact(
val name: String,
val oneName: String,
val phone_number: String
)
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/baseline_cruelty_free_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M16.84,14.52c-0.26,-0.19 -0.62,-0.63 -0.79,-0.84C17.24,12.01 19,8.87 19,5c0,-1.95 -0.74,-3 -2,-3c-1.54,0 -3.96,2.06 -5,5.97C10.96,4.06 8.54,2 7,2C5.74,2 5,3.05 5,5c0,3.87 1.76,7.01 2.95,8.68c-0.17,0.21 -0.53,0.65 -0.79,0.84c-0.5,0.41 -1.66,1.37 -1.66,2.98c0,2.21 1.79,4 4,4c1.55,0 2.5,-0.56 2.5,-0.56s0.95,0.56 2.5,0.56c2.21,0 4,-1.79 4,-4C18.5,15.89 17.34,14.93 16.84,14.52zM9.35,12.2C8.34,10.7 7,8.12 7,5c0,-0.49 0.06,-0.8 0.12,-0.97c0.94,0.31 3.24,2.71 3.38,7.64C10.03,11.79 9.66,11.97 9.35,12.2zM10.5,16.75c-0.28,0 -0.5,-0.34 -0.5,-0.75c0,-0.41 0.22,-0.75 0.5,-0.75S11,15.59 11,16C11,16.41 10.78,16.75 10.5,16.75zM12,19.5c-0.55,0 -1,-0.72 -1,-1c0,-0.28 0.45,-0.5 1,-0.5s1,0.22 1,0.5C13,18.78 12.55,19.5 12,19.5zM13.5,16.75c-0.28,0 -0.5,-0.34 -0.5,-0.75c0,-0.41 0.22,-0.75 0.5,-0.75S14,15.59 14,16C14,16.41 13.78,16.75 13.5,16.75zM13.5,11.67c0.14,-4.93 2.44,-7.33 3.38,-7.64C16.94,4.2 17,4.51 17,5c0,3.12 -1.34,5.7 -2.35,7.2C14.34,11.97 13.97,11.79 13.5,11.67z"/>

</vector>
Binary file added app/src/main/res/drawable/circle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/list_bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/yellow_rectengle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading