-
Notifications
You must be signed in to change notification settings - Fork 32
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주차 과제 제출합니다 #21
base: cleonno3o
Are you sure you want to change the base?
Changes from all commits
92b3b04
325f3ee
bb13e2e
1f6e84c
bf9277b
74f056e
587e425
7c65060
0ecf494
7a19ce2
165ae24
e7fbecc
8bff3b7
45e01cf
055c71b
d41638c
fa15edf
0569683
2f99bf1
79fafd6
5fcea7d
89ea4ba
22fdb19
85b0c35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,21 @@ | ||
# android-contacts | ||
|
||
## Step1 기능목록 | ||
- [x] 추가 버튼을 누르면 정보를 입력할 화면 표시 | ||
- [x] 한 대상의 이름, 전화번호, 메일 등 여러가지 정보를 저장하는 객체에 정보를 저장 | ||
- [x] 이름, 전화번호를 입력하지 않으면 토스트 메시지를 띄우고 저장하지 않음 | ||
- [x] 전화번호 양식이 올바르지 않으면 토스트 메시지를 띄우고 저장하지 않음 | ||
- [x] 이름, 전화번호, 메일 이외의 정보 입력은 더보기를 눌렀을 때 보임 | ||
- [x] 성별의 경우 여성, 남성 중 1가지를 선택할 수 있도록 구현 | ||
- [x] 저장 버튼을 누르면 토스트 메시지를 띄우고 저장 | ||
- [x] 취소 버튼을 누르면 토스트 메시지를 띄우고 저장하지 않음 | ||
|
||
## Step2 기능목록 | ||
- [x] 연락처 등록화면 구현 | ||
- [x] 추가버튼 구현 | ||
- [x] 입력한 연락처를 MainActivity로 전달 | ||
- [x] 저장한 연락처가 없으면 메시지 표시 | ||
- [x] 저장한 연락처가 있으면 모두 표시 | ||
- [x] 많을 경우 스크롤 가능하게 구현 | ||
- [x] 저장된 연락처를 선택하면 해당하는 정보 표시 | ||
- [x] 정보를 저장하지 않으면 확인 창 표시 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package campus.tech.kakao.contacts | ||
|
||
import java.io.Serializable | ||
|
||
data class Contact ( | ||
var name: String, | ||
var phoneNumber: String, | ||
var mail: String, | ||
var birth: String, | ||
var sex: Int, | ||
var memo: String) : Serializable { | ||
val FEMALE: Int = R.id.female | ||
val MALE: Int = R.id.male | ||
companion object CONST { | ||
const val KEY: String = "CONTACT" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
package campus.tech.kakao.contacts | ||
|
||
import android.app.DatePickerDialog | ||
import android.app.Dialog | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.icu.util.Calendar | ||
import android.os.Bundle | ||
import android.text.Editable | ||
import android.text.TextWatcher | ||
import android.util.Log | ||
import android.widget.Button | ||
import android.widget.EditText | ||
import android.widget.RadioGroup | ||
import android.widget.TextView | ||
import android.widget.Toast | ||
import androidx.activity.OnBackPressedCallback | ||
import androidx.activity.OnBackPressedDispatcher | ||
import androidx.activity.enableEdgeToEdge | ||
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.core.view.ViewCompat | ||
import androidx.core.view.WindowInsetsCompat | ||
import androidx.core.view.isEmpty | ||
import androidx.core.widget.addTextChangedListener | ||
import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||
|
||
class ContactActivity : AppCompatActivity() { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_contact) | ||
|
||
val cancelButton: Button = findViewById(R.id.cancel) | ||
val saveButton: Button = findViewById(R.id.save) | ||
|
||
val profile: TextView = findViewById(R.id.profile) | ||
val name: EditText = findViewById(R.id.name) | ||
val phoneNumber: EditText = findViewById(R.id.phone_number) | ||
val mail: EditText = findViewById(R.id.mail) | ||
|
||
val viewMore: ConstraintLayout = findViewById(R.id.view_more) | ||
val moreInfos: ConstraintLayout = findViewById(R.id.more_infos) | ||
val birth: TextView = findViewById(R.id.birthday) | ||
val sex: RadioGroup = findViewById(R.id.sex_radio_group) | ||
val memo: EditText = findViewById(R.id.memo) | ||
|
||
registerBackPressedCallback(name, phoneNumber, mail, birth, sex, memo) | ||
|
||
cancelButton.setOnClickListener { | ||
cancelProcess() | ||
} | ||
|
||
saveButton.setOnClickListener { | ||
saveProcess(name, phoneNumber, mail, birth, sex, memo) | ||
} | ||
|
||
name.addTextChangedListener(nameTextWatcher(profile)) | ||
|
||
viewMore.setOnClickListener { | ||
extendInput(viewMore, moreInfos) | ||
} | ||
|
||
birth.setOnClickListener { | ||
birthInput(birth) | ||
} | ||
} | ||
|
||
fun registerBackPressedCallback(name: EditText, phoneNumber: EditText, mail: EditText, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
birth: TextView, sex: RadioGroup, memo: EditText) { | ||
val onBackPressedCallback = object : OnBackPressedCallback(true) { | ||
override fun handleOnBackPressed() { | ||
if (!isInfoEmpty(name, phoneNumber, mail, birth, sex, memo)) { | ||
buildAlertDialog(this@ContactActivity) | ||
} else finish() | ||
} | ||
} | ||
onBackPressedDispatcher.addCallback(this, onBackPressedCallback) | ||
} | ||
|
||
private fun isInfoEmpty(name: EditText, phoneNumber: EditText, mail: EditText, | ||
birth: TextView, sex: RadioGroup, memo: EditText): Boolean { | ||
return name.text.isEmpty() && | ||
phoneNumber.text.isEmpty() && | ||
mail.text.isEmpty() && | ||
birth.text.isEmpty() && | ||
sex.checkedRadioButtonId == -1 && | ||
memo.text.isEmpty() | ||
} | ||
|
||
private fun buildAlertDialog(aContext: Context) { | ||
MaterialAlertDialogBuilder(aContext) | ||
.setMessage("작성 중인 내용이 있습니다. 정말 나가시겠습니까?") | ||
.setNegativeButton("취소") { dialog, which -> | ||
} | ||
.setPositiveButton("확인") { dialog, which -> | ||
finish() | ||
} | ||
.show() | ||
} | ||
|
||
fun cancelProcess() { | ||
setResult(RESULT_CANCELED, Intent()) | ||
finish() | ||
} | ||
|
||
fun saveProcess(name: EditText, phoneNumber: EditText, mail: EditText, | ||
birth: TextView, sex: RadioGroup, memo: EditText) { | ||
if (isValidInfo(name, phoneNumber)) { | ||
val contact: Contact = saveInfo(name, phoneNumber, mail, birth, sex, memo) | ||
val returnIntent: Intent = Intent(this, MainActivity::class.java) | ||
returnIntent.putExtra(Contact.KEY, contact) | ||
setResult(RESULT_OK, returnIntent) | ||
finish() | ||
} | ||
} | ||
|
||
fun isValidInfo(name: EditText, phoneNumber: EditText): Boolean { | ||
return if (!isValidName(name)) { | ||
false | ||
} else if (!isValidNumber(phoneNumber)) { | ||
false | ||
} else true | ||
} | ||
|
||
private fun isValidName(name: EditText): Boolean { | ||
return if (name.text.toString() == "") { | ||
Toast.makeText(this, "이름은 반드시 입력해야 합니다", Toast.LENGTH_SHORT).show() | ||
false | ||
} else true | ||
} | ||
|
||
private fun isValidNumber(phoneNumber: EditText): Boolean { | ||
val v : Regex = Regex("^[0-9]+$") | ||
return if (v.matches(phoneNumber.text.toString())) { | ||
true | ||
} else if (phoneNumber.text.toString() == "") { | ||
Toast.makeText(this, "전화번호는 반드시 입력해야 합니다", Toast.LENGTH_SHORT).show() | ||
false | ||
} else { | ||
Toast.makeText(this, "전화번호는 숫자로만 구성되어야 합니다", Toast.LENGTH_SHORT).show() | ||
false | ||
} | ||
} | ||
|
||
private fun saveInfo(name: EditText, phoneNumber: EditText, mail: EditText, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기 |
||
birth: TextView, sex: RadioGroup, memo: EditText): Contact { | ||
val nameInfo: String = name.text.toString() | ||
val phoneNumberInfo: String = phoneNumber.text.toString() | ||
val mailInfo: String = mail.text.toString() | ||
val birthInfo: String = birth.text.toString() | ||
val sexInfo: Int = sex.checkedRadioButtonId | ||
val memoInfo: String = memo.text.toString() | ||
|
||
val contact: Contact = Contact(nameInfo, phoneNumberInfo,mailInfo, birthInfo, sexInfo, memoInfo) | ||
return contact | ||
} | ||
|
||
fun nameTextWatcher(profile: TextView): TextWatcher { | ||
return object: TextWatcher { | ||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { | ||
} | ||
|
||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { | ||
} | ||
|
||
override fun afterTextChanged(s: Editable?) { | ||
s?.let { | ||
updateProfile(profile, s.toString()) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun updateProfile(profile: TextView, name: String) { | ||
if (name.isEmpty()) | ||
profile.text = "" | ||
else | ||
profile.text = name[0].toString() | ||
} | ||
|
||
fun extendInput(viewMore: ConstraintLayout, moreInfos: ConstraintLayout) { | ||
viewMore.visibility = ConstraintLayout.GONE | ||
moreInfos.visibility = ConstraintLayout.VISIBLE | ||
} | ||
|
||
fun birthInput(birth: TextView) { | ||
val calendar = Calendar.getInstance() | ||
val cYear = calendar.get(Calendar.YEAR) | ||
val cMonth = calendar.get(Calendar.MONTH) | ||
val cDay = calendar.get(Calendar.DAY_OF_MONTH) | ||
|
||
DatePickerDialog(this, | ||
{ _, year, month, dayOfMonth -> birth.text = "$year-%02d-%02d".format(month + 1, dayOfMonth) }, | ||
cYear, cMonth, cDay).show() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package campus.tech.kakao.contacts | ||
|
||
import android.os.Build | ||
import android.os.Bundle | ||
import android.widget.TextView | ||
import androidx.activity.enableEdgeToEdge | ||
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.core.view.ViewCompat | ||
import androidx.core.view.WindowInsetsCompat | ||
|
||
class ContactInfoActivity : AppCompatActivity() { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_contact_info) | ||
val infoContact = | ||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) | ||
intent.extras?.getSerializable(Contact.KEY,Contact::class.java) | ||
else | ||
intent.extras?.getSerializable(Contact.KEY) as Contact? | ||
|
||
if (infoContact is Contact) { | ||
val infoProfile: TextView = findViewById(R.id.info_profile) | ||
val infoName: TextView = findViewById(R.id.info_name) | ||
val infoPhoneNumber: TextView = findViewById(R.id.info_phone_number) | ||
val infoMail: TextView = findViewById(R.id.info_mail) | ||
val infoBirth: TextView = findViewById(R.id.info_birth) | ||
val infoSex: TextView = findViewById(R.id.info_sex) | ||
val infoMemo: TextView = findViewById(R.id.info_memo) | ||
|
||
matchInfo(infoProfile, infoName, infoPhoneNumber, infoMail, infoBirth, infoSex, infoMemo, infoContact) | ||
} | ||
} | ||
|
||
private fun matchInfo(infoProfile: TextView, infoName: TextView, infoPhoneNumber: TextView, infoMail: TextView, | ||
infoBirth: TextView, infoSex: TextView, infoMemo: TextView, infoContact: Contact) { | ||
|
||
infoProfile.text = infoContact.name[0].toString() | ||
infoName.text = infoContact.name | ||
infoPhoneNumber.text = infoContact.phoneNumber | ||
infoMail.text = infoContact.mail | ||
infoBirth.text = infoContact.birth | ||
infoSex.text = | ||
when (infoContact.sex) { | ||
infoContact.FEMALE -> "여" | ||
infoContact.MALE -> "남" | ||
else -> "" | ||
} | ||
infoMemo.text = infoContact.memo | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package campus.tech.kakao.contacts | ||
|
||
import android.content.Context | ||
import android.content.Intent | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.TextView | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.recyclerview.widget.RecyclerView | ||
|
||
class ContactRecyclerAdapter( | ||
var contactList: MutableList<Contact>, | ||
val inflater: LayoutInflater, | ||
val mContext: Context | ||
) : RecyclerView.Adapter<ContactRecyclerAdapter.ContactViewHolder>() { | ||
inner class ContactViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { | ||
val itemLayout: ConstraintLayout | ||
val profile: TextView | ||
val name: TextView | ||
init { | ||
itemLayout = itemView.findViewById(R.id.item_contact) | ||
itemLayout.setOnClickListener { showContactInfo(mContext, adapterPosition) } | ||
profile = itemView.findViewById(R.id.contact_item_profile) | ||
name = itemView.findViewById(R.id.contact_item_name) | ||
} | ||
} | ||
|
||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContactViewHolder { | ||
val view = inflater.inflate(R.layout.item_contact, parent, false) | ||
return ContactViewHolder(view) | ||
} | ||
|
||
override fun onBindViewHolder(holder: ContactViewHolder, position: Int) { | ||
holder.profile.text = contactList[position].name[0].toString() | ||
holder.name.text = contactList[position].name | ||
} | ||
|
||
override fun getItemCount(): Int { | ||
return contactList.size | ||
} | ||
|
||
private fun showContactInfo(mContext: Context, adapterPosition: Int) { | ||
val contactIntent: Intent = Intent(mContext, ContactInfoActivity::class.java) | ||
contactIntent.putExtra(Contact.KEY, contactList[adapterPosition]) | ||
mContext.startActivity(contactIntent) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기 코드스타일이 조금 이상하네요
커밋하시기 전에 IDE의 reformat code 기능을 이용하면
코드스타일을 일관되게 유지할수 있어요!