diff --git a/README.md b/README.md
index cc0acc5a..f61ce0a0 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,33 @@
-# android-contacts
+# android-contacts - 간단한 연락처 구현(1주차)
+## 구현할 기능 목록
+
+**지정된 형식의 데이터를 입력하는 기능**
+- [x] 문자열을 입력할 수 있는 기능
+- [x] 숫자만 입력할 수 있는 기능
+- [x] 날짜 선택 기능
+- [x] 성별 선택 기능
+
+**더보기 기능**
+- [x] 더보기를 클릭하면 숨겨져 있던 입력 폼을 드러낼 수 있는 기능
+
+**저장 기능**
+- [x] 저장 버튼을 클릭하면 토스트 메세지를 출력
+- [x] 이름, 전화번호의 칸이 채워져 있지 않으면 저장이 되지 않으면 그에 맞는 토스트 메세지를 출력
+
+**취소 기능**
+- [x] 취소 버튼을 클릭하면 토스트 메세지를 출력
+
+## step2 구현할 기능 목록
+
+**연락처 추가 기능**
+- [x] + 버튼을 통해 연락처를 추가하는 창을 띄우는 기능
+
+**연락처 출력 기능**
+- [x] 저장된 연락처들을 간단하게 이름만 띄워주는 기능
+- [x] 각 연락처를 클릭하면 상세 화면을 띄워주는 기능
+- [x] 상세화면에서 적힌 내용만 출력하는 기능
+
+**연락처 저장 기능**
+- [x] 저장 버튼을 누르면 연락처를 저장할 수 있는 기능
+- [x] 뒤로가기 버튼을 누를 때 만약 작성된 내용이 있다면 확인 팝업이 나타나는 기능
+- [x] 취소 버튼을 누를 때 만약 작성된 내용이 있다면 확인 팝업이 나타나는 기능
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index c5add08f..12f60dcb 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -41,6 +41,7 @@ dependencies {
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")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 89dc9d8b..1793994b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,8 +12,14 @@
android:supportsRtl="true"
android:theme="@style/Theme.Contacts"
tools:targetApi="31">
+
+
@@ -23,4 +29,4 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/contacts/DetailActivity.kt b/app/src/main/java/campus/tech/kakao/contacts/DetailActivity.kt
new file mode 100644
index 00000000..8a7bdd91
--- /dev/null
+++ b/app/src/main/java/campus/tech/kakao/contacts/DetailActivity.kt
@@ -0,0 +1,96 @@
+package campus.tech.kakao.contacts
+
+import android.os.Bundle
+import android.view.View
+import android.widget.TextView
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+
+class DetailActivity : AppCompatActivity() {
+ lateinit var name: TextView
+ lateinit var phoneNumber: TextView
+ lateinit var mail: TextView
+ lateinit var birthday: TextView
+ lateinit var gender: TextView
+ lateinit var memo: TextView
+ lateinit var nameInputField: TextView
+ lateinit var phoneNumberInputField: TextView
+ lateinit var mailInputField: TextView
+ lateinit var birthdayInputField: TextView
+ lateinit var genderInputField: TextView
+ lateinit var memoInputField: TextView
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_detail)
+
+ initVar()
+ bindField()
+ setVisibleCompletedFields()
+ }
+
+ fun initVar(){
+ name = findViewById(R.id.name)
+ phoneNumber = findViewById(R.id.phone_number)
+ mail = findViewById(R.id.mail)
+ birthday = findViewById(R.id.birthday)
+ gender = findViewById(R.id.gender)
+ memo = findViewById(R.id.memo)
+ nameInputField = findViewById(R.id.input_name_field)
+ phoneNumberInputField = findViewById(R.id.input_phone_number_field)
+ mailInputField = findViewById(R.id.input_mail_field)
+ birthdayInputField = findViewById(R.id.input_birthday_field)
+ genderInputField = findViewById(R.id.input_gender_field)
+ memoInputField = findViewById(R.id.input_memo_field)
+ }
+
+ fun bindField(){
+ val intent = intent
+ nameInputField.setText(intent.getStringExtra("name"))
+ phoneNumberInputField.setText(intent.getStringExtra("phoneNumber"))
+ mailInputField.setText(intent.getStringExtra("mail"))
+ birthdayInputField.setText(intent.getStringExtra("birthday"))
+ genderInputField.setText(intent.getStringExtra("gender"))
+ memoInputField.setText(intent.getStringExtra("memo"))
+ }
+
+ fun setVisibleCompletedFields() {
+ if(ExistMail()){
+ mail.visibility = View.VISIBLE
+ mailInputField.visibility = View.VISIBLE
+ }
+ if(ExistBirthday()){
+ birthday.visibility = View.VISIBLE
+ birthdayInputField.visibility = View.VISIBLE
+ }
+ if(ExistGender()){
+ gender.visibility = View.VISIBLE
+ genderInputField.visibility = View.VISIBLE
+ }
+ if(ExistMemo()){
+ memo.visibility = View.VISIBLE
+ memoInputField.visibility = View.VISIBLE
+ }
+
+ }
+
+
+
+ fun ExistMail(): Boolean {
+ return mailInputField.text.toString() != ""
+ }
+
+ fun ExistBirthday(): Boolean {
+ return birthdayInputField.text.toString() != ""
+ }
+
+ fun ExistGender(): Boolean {
+ return genderInputField.text.toString() != ""
+ }
+
+ fun ExistMemo(): Boolean {
+ return memoInputField.text.toString() != ""
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/contacts/ListActivity.kt b/app/src/main/java/campus/tech/kakao/contacts/ListActivity.kt
new file mode 100644
index 00000000..ac1a7ca4
--- /dev/null
+++ b/app/src/main/java/campus/tech/kakao/contacts/ListActivity.kt
@@ -0,0 +1,136 @@
+package campus.tech.kakao.contacts
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+
+class ListActivity : AppCompatActivity() {
+ lateinit var resultLauncher: ActivityResultLauncher
+ lateinit var descriptionText: TextView
+ lateinit var plusButton: TextView
+ lateinit var recyclerView: RecyclerView
+ lateinit var contactList: MutableList
+ lateinit var adapter: RecyclerViewAdapter
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_list)
+
+ initVar()
+ initListener()
+
+ }
+
+ fun initVar(){
+ contactList = mutableListOf()
+ adapter = RecyclerViewAdapter(contactList, LayoutInflater.from(this), this)
+ plusButton = findViewById(R.id.plus_item_button)
+ descriptionText = findViewById(R.id.description_text)
+ initRecyclerView()
+ initResultLauncher()
+ }
+
+ fun initRecyclerView() {
+ recyclerView = findViewById(R.id.recyclerView)
+ recyclerView.adapter = adapter
+ recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
+ }
+
+ fun initResultLauncher() {
+ resultLauncher =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ val contact = Contact(
+ result.data?.getStringExtra("name") ?: "",
+ result.data?.getStringExtra("phoneNumber") ?: "",
+ result.data?.getStringExtra("mail") ?: "",
+ result.data?.getStringExtra("birthday") ?: "",
+ result.data?.getStringExtra("gender") ?: "",
+ result.data?.getStringExtra("memo") ?: "",
+ )
+ Log.d("contact2", contact.name)
+ contactList.add(contact)
+ setDescriptionTextVisibilityGone()
+ adapter.notifyItemInserted(contactList.size)
+ }
+ }
+ }
+ fun initListener(){
+ plusButton.setOnClickListener {
+ moveToAddContact()
+ }
+ }
+ fun moveToAddContact() {
+ val intent = Intent(this@ListActivity, MainActivity::class.java)
+ resultLauncher.launch(intent)
+ }
+
+ fun setDescriptionTextVisibilityGone() {
+ descriptionText.visibility = View.GONE
+ }
+
+}
+
+class RecyclerViewAdapter(
+ var contactList: MutableList,
+ var inflater: LayoutInflater,
+ var context: Context
+) : RecyclerView.Adapter() {
+
+ inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ val userTitle: TextView
+ val userName: TextView
+
+ init {
+ userTitle = itemView.findViewById(R.id.user_title)
+ userName = itemView.findViewById(R.id.user_name)
+ itemView.setOnClickListener {
+ val position: Int = adapterPosition
+ val intent = Intent(context, DetailActivity::class.java)
+ val sendContact = contactList.get(position)
+ intent.putExtra("name", sendContact.name)
+ intent.putExtra("phoneNumber", sendContact.phoneNumber)
+ intent.putExtra("mail", sendContact.mail)
+ intent.putExtra("birthday", sendContact.birthday)
+ intent.putExtra("gender", sendContact.gender)
+ intent.putExtra("memo", sendContact.memo)
+ context.startActivity(intent)
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val view = inflater.inflate(R.layout.contact_item, parent, false)
+ return ViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.userTitle.text = contactList.get(position).name[0].toString()
+ holder.userName.text = contactList.get(position).name
+ }
+
+ override fun getItemCount(): Int {
+ return contactList.size
+ }
+}
+
+class Contact(
+ var name: String,
+ var phoneNumber: String,
+ var mail: String,
+ var birthday: String,
+ var gender: String,
+ var memo: String
+) {}
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/contacts/MainActivity.kt b/app/src/main/java/campus/tech/kakao/contacts/MainActivity.kt
index 7aae79fe..03f9c44a 100644
--- a/app/src/main/java/campus/tech/kakao/contacts/MainActivity.kt
+++ b/app/src/main/java/campus/tech/kakao/contacts/MainActivity.kt
@@ -1,11 +1,201 @@
package campus.tech.kakao.contacts
+import android.app.DatePickerDialog
+import android.content.Context
+import android.content.DialogInterface
import android.os.Bundle
+import android.view.View
+import android.widget.EditText
+import android.widget.RadioGroup
+import android.widget.TextView
+import android.widget.Toast
+import androidx.activity.OnBackPressedCallback
+import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
+const val EXIST_NAME_AND_PHONE_NUMBER = 1
+const val NOT_EXIST_NAME = 2
+const val NOT_EXIST_PHONE_NUMBER = 3
+
class MainActivity : AppCompatActivity() {
+ lateinit var name : EditText
+ lateinit var phoneNumber : EditText
+ lateinit var mail : EditText
+ lateinit var gender : EditText
+ lateinit var genderRadioGroup : RadioGroup
+ lateinit var memo : EditText
+ lateinit var birthday : EditText
+ lateinit var moreInfoButton : TextView
+
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ initVar()
+ initListener()
+ onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
+ }
+
+ private val onBackPressedCallback = object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ finishContactAdding(this@MainActivity)
+ }
+ }
+
+ fun initListener(){
+ saveButtonSetOnClickListener(this)
+ cancelButtonSetOnClickListener(this)
+ moreButtonSetOnClickListener()
+ birthdayFieldSetOnclickListener()
+ genderFieldSetOnChangeListener()
+ }
+
+ fun finishContactAdding(context: Context){
+ if(isNowWritting())
+ displayCancelDialog(context)
+ else
+ finish()
+ }
+
+
+ fun displayCancelDialog(context: Context){
+ val alert = AlertDialog.Builder(this@MainActivity)
+ alert.setTitle("")
+ alert.setMessage("작성중인 내용이 있습니다. 정말 나가시겠습니까?")
+ alert.setPositiveButton("작성하기", DialogInterface.OnClickListener{ dialog, which ->
+ })
+ alert.setNegativeButton("나가기", DialogInterface.OnClickListener { dialog, which ->
+ displayCancelToastMessage(context)
+ finish()
+ })
+ alert.show()
+ }
+
+ fun isNowWritting() : Boolean{
+ return if(name.text.toString() != "" || phoneNumber.text.toString() != "" || mail.text.toString() != "" || birthday.text.toString() != "" || gender.text.toString() != "" || memo.text.toString() != "")
+ true
+ else false
+ }
+
+ fun cancelButtonSetOnClickListener(context : Context){
+ findViewById(R.id.button_cancel).setOnClickListener(){
+ finishContactAdding(context)
+ }
+ }
+
+ fun displayCancelToastMessage(context: Context){
+ val cancelMessage = Toast.makeText(context, "취소 되었습니다", Toast.LENGTH_SHORT)
+ cancelMessage.show()
+ }
+
+ fun saveButtonSetOnClickListener(context : Context){
+ findViewById(R.id.button_save).setOnClickListener(){
+ saveContact(context)
+ }
+ }
+
+ fun existNameAndPhoneNum() : Boolean{
+ val checkNum = checkNameAndPhoneNum()
+ return if(checkNum == NOT_EXIST_NAME || checkNum == NOT_EXIST_PHONE_NUMBER) false
+ else true
+ }
+
+ fun saveContact(context:Context){
+ if (existNameAndPhoneNum()){
+ displaySaveMessage(context)
+ intent.putExtra("name", name.text.toString())
+ intent.putExtra("phoneNumber", phoneNumber.text.toString())
+ intent.putExtra("mail", mail.text.toString())
+ intent.putExtra("birthday", birthday.text.toString())
+ intent.putExtra("gender", gender.text.toString())
+ intent.putExtra("memo", memo.text.toString())
+ setResult(RESULT_OK, intent)
+ finish()
+ }
+ else {
+ displaySaveMessage(context)
+ }
+
+ }
+
+ fun displaySaveMessage(context: Context){
+ val text = getToastMessageToNameAndPhoneNum()
+ val saveMessage = Toast.makeText(context, text, Toast.LENGTH_SHORT)
+ saveMessage.show()
+ }
+
+
+ fun checkNameAndPhoneNum() : Int{
+ return if (name.text.toString() == ""){
+ name.requestFocus()
+ NOT_EXIST_NAME
+ } else if(phoneNumber.text.toString() == ""){
+ phoneNumber.requestFocus()
+ NOT_EXIST_PHONE_NUMBER
+ } else{
+ EXIST_NAME_AND_PHONE_NUMBER
+ }
+ }
+
+ fun getToastMessageToNameAndPhoneNum() : String{
+ val checkNum = checkNameAndPhoneNum()
+ return when(checkNum){
+ EXIST_NAME_AND_PHONE_NUMBER -> "저장이 완료되었습니다"
+ NOT_EXIST_NAME -> "이름을 입력해 주세요"
+ NOT_EXIST_PHONE_NUMBER -> "전화번호를 입력해 주세요"
+ else -> "오류"
+ }
+ }
+
+ fun moreButtonSetOnClickListener(){
+ moreInfoButton.setOnClickListener(){
+ setInputFieldVisible()
+ }
+ }
+
+ fun setInputFieldVisible(){
+ birthday.visibility = View.VISIBLE
+ gender.visibility = View.VISIBLE
+ genderRadioGroup.visibility = View.VISIBLE
+ memo.visibility = View.VISIBLE
+ moreInfoButton.visibility = View.GONE
+ }
+
+ fun birthdayFieldSetOnclickListener(){
+ birthday.setOnClickListener(){
+ setBirthday()
+ }
+ }
+
+ fun setBirthday(){
+ val datePicker = DatePickerDialog(this, DatePickerDialog.OnDateSetListener {
+ _, year, month, day ->
+ birthday.setText("${year}/${month}/${day}")
+ }, 2000, 1, 1).show()
+ }
+
+ fun genderFieldSetOnChangeListener(){
+ genderRadioGroup.setOnCheckedChangeListener { _, id ->
+ fillGenderField(id)
+ }
+ }
+ fun fillGenderField(id : Int){
+ when(id){
+ R.id.button_woman -> gender.setText("여성")
+ R.id.button_man -> gender.setText("남성")
+ else -> gender.setText("")
+ }
+ }
+
+ fun initVar(){
+ name = findViewById(R.id.input_name)
+ phoneNumber = findViewById(R.id.input_phone_number)
+ mail = findViewById(R.id.input_mail)
+ birthday = findViewById(R.id.input_birthday)
+ gender = findViewById(R.id.input_gender)
+ genderRadioGroup = findViewById(R.id.gender_radio_group)
+ memo = findViewById(R.id.input_memo)
+ moreInfoButton = findViewById(R.id.more_info_button)
}
}
+
diff --git a/app/src/main/res/drawable/input_form.xml b/app/src/main/res/drawable/input_form.xml
new file mode 100644
index 00000000..2abf3180
--- /dev/null
+++ b/app/src/main/res/drawable/input_form.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/item.xml b/app/src/main/res/drawable/item.xml
new file mode 100644
index 00000000..766b434e
--- /dev/null
+++ b/app/src/main/res/drawable/item.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/yellow_box.xml b/app/src/main/res/drawable/yellow_box.xml
new file mode 100644
index 00000000..2a670c65
--- /dev/null
+++ b/app/src/main/res/drawable/yellow_box.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/yellow_circle.xml b/app/src/main/res/drawable/yellow_circle.xml
new file mode 100644
index 00000000..29375f91
--- /dev/null
+++ b/app/src/main/res/drawable/yellow_circle.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml
new file mode 100644
index 00000000..ad84b28e
--- /dev/null
+++ b/app/src/main/res/layout/activity_detail.xml
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_list.xml b/app/src/main/res/layout/activity_list.xml
new file mode 100644
index 00000000..8892367e
--- /dev/null
+++ b/app/src/main/res/layout/activity_list.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 24d17df2..f73d1e58 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -7,13 +7,193 @@
android:layout_height="match_parent"
tools:context=".MainActivity">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintLeft_toRightOf="@+id/button_cancel"
+ android:text="저장"
+ android:gravity="center"
+ android:textSize="20sp"/>
+
diff --git a/app/src/main/res/layout/contact_item.xml b/app/src/main/res/layout/contact_item.xml
new file mode 100644
index 00000000..98045290
--- /dev/null
+++ b/app/src/main/res/layout/contact_item.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
\ No newline at end of file