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주차 과제 #37

Open
wants to merge 24 commits into
base: jsh00325
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
62588b0
docs: Add Program Description & Feature
jsh00325 Jun 24, 2024
037366f
feat: Add Contact Input Layout
jsh00325 Jun 25, 2024
fd20c6d
feat: Add a Button for Input More Information
jsh00325 Jun 25, 2024
9cca3c5
feat: Add a Feature for Cancel Button
jsh00325 Jun 25, 2024
9946f38
feat: Add a Feature for Save Contact
jsh00325 Jun 26, 2024
7ea2ec6
docs: Update Step2 Program Features
jsh00325 Jun 28, 2024
763bf16
feat: Add Contact Item Layout
jsh00325 Jun 28, 2024
4cfbaa7
feat: Add Contact List Layout w. RecyclerView
jsh00325 Jun 28, 2024
7c70c0c
feat: Add Contact Info Layout
jsh00325 Jun 28, 2024
2eafb0f
feat: Create Adapter for ContactsList & Connect with RecyclerView
jsh00325 Jun 28, 2024
4e22289
feat: Connect With Register Activity using FloatingActionButton
jsh00325 Jun 28, 2024
e10a86e
feat: Add Cancle Button's Feature On Register Activity
jsh00325 Jun 28, 2024
c60d8dd
feat: Add AlertDialog When User Press Back Button
jsh00325 Jun 28, 2024
7066116
feat: Save Contact and Update RecyclerView with New Item
jsh00325 Jun 28, 2024
347235d
feat: Add Click Lister at ContactItem
jsh00325 Jun 28, 2024
0e2ad0a
feat: Fill Contact Info At ContactInfoActivity
jsh00325 Jun 28, 2024
39e966c
style: Reformat code
jsh00325 Jul 1, 2024
3b98422
refactor: Change When to If
jsh00325 Jul 1, 2024
7df2bd2
refactor: Add Constant Value
jsh00325 Jul 1, 2024
8637994
refactor: Add Constant Value 2
jsh00325 Jul 1, 2024
08a428a
refactor: Change Method Name
jsh00325 Jul 1, 2024
b45cc13
refactor: Change Linear Layout To Constraint Layout
jsh00325 Jul 2, 2024
2033f07
refactor: use isVisible instead of let
jsh00325 Jul 2, 2024
a4cecd4
refactor: Reduce Layout Depth
jsh00325 Jul 2, 2024
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
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,47 @@
# android-contacts

## 📄 프로그램 설명

연락처를 관리하는 안드로이드 앱입니다.

간단하게 연락처를 추가하는 기능이 있습니다.

## 🎯 1단계(연락처 추가) 구현할 기능

- [X] 연락처와 이름, 전화번호를 입력 받는 레이아웃 제작

- [X] 전화번호는 숫자만 입력 가능하도록 구현한다.

- [X] 더보기 버튼을 통해 생일, 성별, 메모를 입력 받는 레이아웃 제작

- [X] 버튼을 누르면 입력 폼이 확장되도록 구현한다.

- [X] 성별은 라디오 버튼을 통해 남성, 여성을 선택할 수 있도록 구현한다.

- [X] 저장 버튼을 누르면 입력한 정보를 저장

- [X] 이름과 전화번호가 입력되지 않았을 때, 토스트 메시지를 띄워 경고한다.

- [X] 저장이 완료되면 '저장이 완료 되었습니다'라는 토스트 메시지를 띄워 저장되었음을 알린다.

- [X] 취소 버튼을 누르면 입력한 정보를 초기화

- [X] '취소 되었습니다'라는 토스트 메시지를 띄워 초기화 되었음을 알린다.

## 🎯 2단계(연락처 목록) 구현할 기능

- [X] RecyclerView를 활용하여 연락처 목록을 보여주는 레이아웃 제작

- [X] 연락처의 목록을 구성하는 item 레이아웃 제작

- [X] 연락처의 상세 정보를 확인하는 레이아웃 제작

- [X] 연락처 목록에서 연락처를 클릭하면 상세 정보를 확인할 수 있도록 구현

- [X] 추가하기 버튼 클릭 시 기존의 등록 페이지가 나타나는 기능 구현

- [X] 등록 페이지에서 취소 버튼 클릭 시 목록으로 돌아가는 기능 구현

- [X] 등록 페이지에서 저장 버튼 클릭 시 목록에 추가되는 기능 구현

- [X] 뒤로가기 버튼 클릭 시 확인 팝업 띄우기
71 changes: 36 additions & 35 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.android.application")
id("org.jetbrains.kotlin.android")
}

android {
namespace = "campus.tech.kakao.contacts"
compileSdk = 34
namespace = "campus.tech.kakao.contacts"
compileSdk = 34

defaultConfig {
applicationId = "campus.tech.kakao.contacts"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"
defaultConfig {
applicationId = "campus.tech.kakao.contacts"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}

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")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
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")
testImplementation("junit:junit:4.13.2")
JSpiner marked this conversation as resolved.
Show resolved Hide resolved
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
13 changes: 11 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,23 @@
android:theme="@style/Theme.Contacts"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:name=".ContactInfoActivity"
android:exported="true" />
<activity
android:name=".ContactsListActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ContactRegisterActivity"
android:exported="true" />
<activity
android:name=".MainActivity"
android:exported="true" />
</application>

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

import java.io.Serializable

data class ContactData(
val name: String,
val phone: String,
var email: String? = null,
var birthday: String? = null,
var isFemale: Boolean? = null,
var memo: String? = null
) : Serializable {
companion object {
const val CONTACT_DATA_KEY: String = "contactData"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package campus.tech.kakao.contacts

import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible

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

val contactDate =
if (Build.VERSION.SDK_INT >= 33) {
intent.getSerializableExtra(ContactData.CONTACT_DATA_KEY, ContactData::class.java)
} else {
intent.getSerializableExtra(ContactData.CONTACT_DATA_KEY) as ContactData?
}

contactDate?.let {
findViewById<TextView>(R.id.contactName).text = it.name
findViewById<TextView>(R.id.contactPhone).text = it.phone

findViewById<LinearLayout>(R.id.contact_mail_layout).isVisible = it.email != null
findViewById<TextView>(R.id.contactMail).text = it.email

findViewById<LinearLayout>(R.id.contact_birthday_layout).isVisible = it.birthday != null
findViewById<TextView>(R.id.contactBirthday).text = it.birthday

findViewById<LinearLayout>(R.id.contact_Sex_layout).isVisible = it.isFemale != null
findViewById<TextView>(R.id.contactSex).text = when (it.isFemale) {
true -> "여성"
false -> "남성"
else -> "알 수 없음"
}

findViewById<LinearLayout>(R.id.contact_memo_layout).isVisible = it.memo != null
findViewById<TextView>(R.id.contactMemo).text = it.memo
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package campus.tech.kakao.contacts

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.RadioButton
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

class ContactRegisterActivity : AppCompatActivity() {
private lateinit var nameInputView: EditText
private lateinit var phoneInputView: EditText
private lateinit var emailInputView: EditText
private lateinit var birthdayInputView: EditText
private lateinit var femaleRadioButton: RadioButton
private lateinit var maleRadioButton: RadioButton
private lateinit var memoInputView: EditText

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

setMoreInfoVisibility()

nameInputView = findViewById(R.id.contactName)
phoneInputView = findViewById(R.id.contactPhone)
emailInputView = findViewById(R.id.contactMail)
birthdayInputView = findViewById(R.id.contactBirthday)
femaleRadioButton = findViewById(R.id.femaleRadioButton)
maleRadioButton = findViewById(R.id.maleRadioButton)
memoInputView = findViewById(R.id.contactMemo)

findViewById<Button>(R.id.cancelButton).setOnClickListener {
Toast.makeText(this@ContactRegisterActivity, "취소되었습니다.", Toast.LENGTH_SHORT).show()
finish()
}

findViewById<Button>(R.id.saveButton).setOnClickListener {
if (checkRequiredFields()) {
val intent = Intent()
intent.putExtra(ContactData.CONTACT_DATA_KEY, getContactInfoFromView())
setResult(RESULT_OK, intent)
Toast.makeText(this@ContactRegisterActivity, "저장되었습니다.", Toast.LENGTH_SHORT).show()
finish()
}
}

onBackPressedDispatcher.addCallback(backPressedCallback)
}

private val backPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
val dialogBuilder = AlertDialog.Builder(this@ContactRegisterActivity)
dialogBuilder.setMessage("작성중인 내용이 있습니다. 정말 나가시겠습니까?")
dialogBuilder.setNegativeButton("작성하기", null)
dialogBuilder.setPositiveButton("나가기") { dialog, which ->
Toast.makeText(this@ContactRegisterActivity, "취소되었습니다.", Toast.LENGTH_SHORT).show()
finish()
}
dialogBuilder.show()
}
}

private fun setMoreInfoVisibility() {
findViewById<View>(R.id.moreInfoBackground).setOnClickListener { moreInfoBackground ->
findViewById<EditText>(R.id.contactBirthday).visibility = View.VISIBLE
findViewById<View>(R.id.contactGenderBackground).visibility = View.VISIBLE
findViewById<TextView>(R.id.contactGenderTextView).visibility = View.VISIBLE
findViewById<RadioGroup>(R.id.contactGenderRadioGroup).visibility = View.VISIBLE
findViewById<EditText>(R.id.contactMemo).visibility = View.VISIBLE

moreInfoBackground.visibility = View.GONE
findViewById<TextView>(R.id.moreInfoTextView).visibility = View.GONE
findViewById<ImageView>(R.id.moreInfoImageView).visibility = View.GONE
}
}

private fun checkRequiredFields(): Boolean {
return if (nameInputView.text.isEmpty()) {
Toast.makeText(this@ContactRegisterActivity, "이름은 필수 입력사항입니다.", Toast.LENGTH_SHORT)
.show()
false
} else if (phoneInputView.text.isEmpty()) {
Toast.makeText(this@ContactRegisterActivity, "전화번호는 필수 입력사항입니다.", Toast.LENGTH_SHORT)
.show()
false
} else true
}

private fun getContactInfoFromView(): ContactData = ContactData(
name = nameInputView.text.toString(),
phone = phoneInputView.text.toString(),
email = when {
emailInputView.text.isEmpty() -> null
else -> emailInputView.text.toString()
},
birthday = when {
birthdayInputView.text.isEmpty() -> null
else -> birthdayInputView.text.toString()
},
isFemale = when {
femaleRadioButton.isChecked -> true
maleRadioButton.isChecked -> false
else -> null
},
memo = when {
memoInputView.text.isEmpty() -> null
else -> memoInputView.text.toString()
}
)
}
Loading