CSM


πŸ‘†Go to GitHub by clicking the image above!πŸ‘†


What is this?
Mentoring Application for Christian Students Who Will Enter the University


Tech Stack
Kotlin


Organization
java/
β”œβ”€β”€ com.suwonccc.csmproject/
β”‚ β”œβ”€β”€ alarmpage_fragment/
β”‚ β”‚ β”œβ”€β”€ AlarmInfo
β”‚ β”‚ β”œβ”€β”€ AlarmInfoDAO
β”‚ β”‚ β”œβ”€β”€ AlarmpageFragment
β”‚ β”‚ └── AlarmPageRecyclerView.kt
β”‚ β”œβ”€β”€ etcpage/
β”‚ β”‚ β”œβ”€β”€ Etcpage_disconnect
β”‚ β”‚ β”œβ”€β”€ Etcpage_modify_mentee
β”‚ β”‚ β”œβ”€β”€ Etcpage_modify_mentor
β”‚ β”‚ β”œβ”€β”€ Etcpage_mymentee
β”‚ β”‚ β”œβ”€β”€ Etcpage_mymentee_list
β”‚ β”‚ β”œβ”€β”€ Ectpage_mymentor
β”‚ β”‚ β”œβ”€β”€ Ectpage_nomentee
β”‚ β”‚ β”œβ”€β”€ Ectpage_nomentor
β”‚ β”‚ └── EtcpageFragment.kt
β”‚ β”œβ”€β”€ firstpage_fragment/
β”‚ β”‚ β”œβ”€β”€ LoginComplete
β”‚ β”‚ β”œβ”€β”€ LoginExtraInfo
β”‚ β”‚ β”œβ”€β”€ LoginMain
β”‚ β”‚ β”œβ”€β”€ LoginMentee
β”‚ β”‚ β”œβ”€β”€ LoginMentor
β”‚ β”‚ └── LoginProfile
β”‚ β”œβ”€β”€ mainpage_fragment/
β”‚ β”‚ β”œβ”€β”€ MainpageFragment
β”‚ β”‚ β”œβ”€β”€ MainpageWaitMentorFragment.kt
β”‚ β”‚ β”œβ”€β”€ MainpageWelcomeMenteeFragment.kt
β”‚ β”‚ β”œβ”€β”€ MainpageWelcomeMentorFragment
β”‚ β”‚ └── MainSearchMentorActivity
β”‚ β”œβ”€β”€ recyclerview/
β”‚ β”‚ β”œβ”€β”€ mentee.kt
β”‚ β”‚ β”œβ”€β”€ MenteelistAdapter
β”‚ β”‚ └── SearchMentorlistAdapter
β”‚ β”œβ”€β”€ ChattingpageFragment.kt
β”‚ β”œβ”€β”€ Firstpage
β”‚ β”œβ”€β”€ MainActivity
β”‚ β”œβ”€β”€ MessagingService
β”‚ └── UserstorypageFragment.kt

1. Login Main

λ ˆμ΄μ•„μ›ƒ

1) ConstraintLayout

  • Chain을 μ‚¬μš©ν•˜μ—¬ ν™”λ©΄ 해상도에 따라 각 μš”μ†Œμ˜ μœ„μΉ˜κ°€ 많이 달라지지 μ•Šκ²Œ ν•˜κΈ° μœ„ν•¨


2) ImageButton

  • backgroundλ₯Ό 투λͺ…ν•˜κ²Œ ν•˜κ³ , src에 이미지 νŒŒμΌμ„ 넣을 것


ν”„λž˜κ·Έλ¨ΌνŠΈ

1) onCreateView vs onViewCreated

  • onCreate(): ν•΄λ‹Ή μ½œλ°±μ€ Fragmentκ°€ 생성될 λ•Œ 단 ν•œ 번만 ν˜ΈμΆœλœλ‹€. 데이터와 같은 λ¦¬μ†ŒμŠ€ μ΄ˆκΈ°ν™” μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” μ ν•©ν•˜λ‹€.
  • onCreateView(): ν•΄λ‹Ή μ½œλ°±μ€ Viewκ°€ μƒμ„±λ˜μ–΄ λ§€κ°œλ³€μˆ˜λ‘œ μ‚¬μš© κ°€λŠ₯ν•œ μ‹œμ μ΄λ‹€. λ˜ν•œ, Fragmentκ°€ back stackμ—μ„œ λ˜λŒμ•„μ˜€λŠ” 지점이닀.
  • onViewCreated(): ν•΄λ‹Ή μ½œλ°±μ€ onCreateView()κ°€ 호좜된 직후 ν˜ΈμΆœλœλ‹€. λ·°κ°€ μ™„μ „νžˆ μƒμ„±λ˜μ–΄ μžˆλŠ” 지점이닀.


2) Jetpack Navigation

  • NavHost: 탐색 κ·Έλž˜ν”„μ—μ„œ λŒ€μƒμ„ ν‘œμ‹œν•˜λŠ” 빈 μ»¨ν…Œμ΄λ„ˆ
  • NavController: NavHostμ—μ„œ μ•± 탐색을 κ΄€λ¦¬ν•˜λŠ” 객체
  • login_nav_graph.xml을 λ³„λ„λ‘œ λ§Œλ“€μ–΄μ€Œ



2. Login Profile

λ ˆμ΄μ•„μ›ƒ

1) NestedScrollView

  • ScrollViewλ₯Ό μ‚¬μš©ν•  λ•Œμ™€ 달리, λͺ¨λ“  Viewκ°€ ν•¨κ»˜ 슀크둀이 될 수 있음


2) CircleImageView

  • implementation 'de.hdodenhof:circleimageview:3.0.0'


ν”„λž˜κ·Έλ¨ΌνŠΈ

1) PopupWindow

  • fragment_login_profile_change_dialog.xml을 λ³„λ„λ‘œ λ§Œλ“€μ–΄μ€Œ


2) PopupMenu

var popUpMenu = PopupMenu(wrapper, popup_req_btn)

popUpMenu.menu.add(Menu.NONE, 0, 0, "naver.com")
popUpMenu.menu.add(Menu.NONE, 1, 1, "gmail.com")
popUpMenu.menu.add(Menu.NONE, 2, 2, "hanmail.net")


3) 가러리 μ ‘κ·Ό

  • 가러리 κΆŒν•œ λΆ€μ—¬ -> onRequestPermissionsResult()μ—μ„œ ν•΄λ‹Ήν•˜λŠ” requestCode에 따라 dispatchPickGalleryIntent() μ‹€ν–‰ -> onActivityResult()μ—μ„œ ν•΄λ‹Ήν•˜λŠ” resultCode에 따라 launchImageCrop() μ‹€ν–‰


4) 카메라 μ ‘κ·Ό

  • 카메라 κΆŒν•œ λΆ€μ—¬ -> onRequestPermissionsResult()μ—μ„œ ν•΄λ‹Ήν•˜λŠ” requestCode에 따라 dispatchTakePictureIntent() μ‹€ν–‰ -> onActivityResult()μ—μ„œ ν•΄λ‹Ήν•˜λŠ” resultCode에 따라 galleryAddPic() μ‹€ν–‰



3. Login Mentor/Mentee

λ ˆμ΄μ•„μ›ƒ

1) AutoCompleteTextView

  • μžλ™μ™„μ„± κΈ°λŠ₯을 μœ„ν•΄ μ‚¬μš©
  • android:completionThreshold="2": 문자의 κ°œμˆ˜κ°€ 2개일 λ•ŒλΆ€ν„° μžλ™μ™„μ„± 검색 μ‹€ν–‰


2) Button Selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- ν΄λ¦­ν–ˆμ„ 경우 -->
    <item android:state_pressed="true" android:drawable="@drawable/firstpage_btn_next_pressed" />
    <item android:state_selected="true" android:drawable="@drawable/firstpage_btn_next_pressed" />
    <!-- ν΄λ¦­ν•˜μ§€ μ•Šμ€ 경우 -->
    <item android:state_pressed="false" android:drawable="@drawable/firstpage_btn_next" />
    <item android:state_selected="false" android:drawable="@drawable/firstpage_btn_next" />
</selector>
  • selector_next_btn.xml을 λ³„λ„λ‘œ λ§Œλ“€μ–΄μ€Œ(drawable 폴더에)
  • state_pressed: λ·°κ°€ λˆŒλ Έμ„ λ•Œ(ν„°μΉ˜λ‚˜ 클릭이 λ°œμƒν–ˆμ„ λ•Œ)
  • state_selected: λ·°λ₯Ό μ„ νƒν–ˆμ„ λ•Œ(λ°©ν–₯ν‚€λ‘œ μ΄λ™ν•˜λ‹€κ°€ μ„ νƒν–ˆμ„ λ•Œ)
  • state_enabled: μ‚¬μš©ν•  수 μžˆλŠ” μƒνƒœμΌ λ•Œ(ν„°μΉ˜λ‚˜ 클릭 이벀트 등을 받을 수 μžˆλŠ” μƒνƒœμΌ λ•Œ)


ν”„λž˜κ·Έλ¨ΌνŠΈ

학ꡐ 검색 μžλ™μ™„μ„±

  • dataλ₯Ό ArrayList에 λ„£μ–΄μ£Όκ³ , ArrayAdapterλ₯Ό μ΄μš©ν•˜μ—¬ 이것을 μ–΄λ–»κ²Œ 보여쀄지 μ§€μ •ν•œλ‹€.
val textView = view.findViewById(R.id.mentor_school_edittext) as AutoCompleteTextView
val universities: Array<out String> = resources.getStringArray(R.array.universities_array)
ArrayAdapter<String>(requireContext(), android.R.layout.simple_list_item_1, universities).also { adapter ->
  textView.setAdapter(adapter)
}
</selector>
  • also: μˆ˜μ‹  객체 λžŒλ‹€κ°€ μ „λ‹¬λœ μˆ˜μ‹  객체λ₯Ό μ „ν˜€ μ‚¬μš© ν•˜μ§€ μ•Šκ±°λ‚˜ μˆ˜μ‹  객체의 속성을 λ³€κ²½ν•˜μ§€ μ•Šκ³  μ‚¬μš©ν•˜λŠ” 경우 also λ₯Ό μ‚¬μš©
  • ν™•μž₯ν•¨μˆ˜: 객체λ₯Ό μ‚¬μš©ν•  λ•Œ λͺ…령문듀을 λΈ”λŸ­μœΌλ‘œ λ¬Άμ–΄μ„œ κ°„κ²°ν•˜κ²Œ μ‚¬μš©ν•  수 있게 ν•΄μ£ΌλŠ” ν•¨μˆ˜



4. Login Extra Info

λ ˆμ΄μ•„μ›ƒ

TableLayout

  • <TableRow>둜 ꡬ성
  • android:completionThreshold="2": 문자의 κ°œμˆ˜κ°€ 2개일 λ•ŒλΆ€ν„° μžλ™μ™„μ„± 검색 μ‹€ν–‰


ν”„λž˜κ·Έλ¨ΌνŠΈ

각 λ²„νŠΌ μœ νš¨μ„± 체크

  • λΉ„μ–΄ μžˆλŠ”μ§€ 확인
  • μ„ νƒν•œ λ²„νŠΌμ˜ κ°œμˆ˜κ°€ 2개λ₯Ό λ„˜λŠ”μ§€ 확인



5. Login Complete

ν”„λž˜κ·Έλ¨ΌνŠΈ

Mainpage Activity둜 이동

activity?.let{
  val intent = Intent (it, MainActivity::class.java)

  intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
  it.startActivity(intent)
}
  • let: μˆ˜μ‹  객체의 속성 λ³€κ²½ κ°€λŠ₯
  • T?.let { } ν˜•νƒœμ—μ„œλŠ” non-null 체크 κ°€λŠ₯
  • cf> with도 μˆ˜μ‹  객체의 속성을 λ³€κ²½ν•  수 μžˆμ§€λ§Œ thisλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€λŠ” 차이점 쑴재



6. ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°

apply, with, let, also, run ν•¨μˆ˜μ˜ 차이점

  1. λ²”μœ„ 지정 ν•¨μˆ˜ 의 ν˜ΈμΆœμ‹œμ— μˆ˜μ‹  객체가 맀개 λ³€μˆ˜λ‘œ λͺ…μ‹œμ μœΌλ‘œ μ „λ‹¬λ˜κ±°λ‚˜ μˆ˜μ‹  객체의 ν™•μž₯ ν•¨μˆ˜λ‘œ μ•”μ‹œμ  μˆ˜μ‹  객체 둜 μ „λ‹¬λœλ‹€.
  2. λ²”μœ„ 지정 ν•¨μˆ˜ 의 μˆ˜μ‹  객체 지정 λžŒλ‹€ 에 μ „λ‹¬λ˜λŠ” μˆ˜μ‹  객체가 λͺ…μ‹œμ  맀개 λ³€μˆ˜ 둜 전달 λ˜κ±°λ‚˜ μˆ˜μ‹  객체의 ν™•μž₯ ν•¨μˆ˜λ‘œ μ•”μ‹œμ  μˆ˜μ‹  객체둜 μ½”λ“œ 블둝 λ‚΄λΆ€λ‘œ 전달 λœλ‹€.
  3. λ²”μœ„ 지정 ν•¨μˆ˜μ˜ 결과둜 μˆ˜μ‹  객체λ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜κ±°λ‚˜ μˆ˜μ‹  객체 지정 λžŒλ‹€ 의 μ‹€ν–‰ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.


inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    return receiver.block()
}
  • 인자둜 λ°›λŠ” 객체λ₯Ό μ΄μ–΄μ§€λŠ” λΈ”λ‘μ˜ λ¦¬μ‹œλ²„λ‘œ 전달
  • λΈ”λ‘μ˜ κ²°κ³Όκ°’ λ°˜ν™˜
  • run()κ³Ό 맀우 λΉ„μŠ·(λ¦¬μ‹œλ²„λ‘œ 전달할 객체가 어디에 μœ„μΉ˜ν•˜λŠ”μ§€λ§Œ 닀름)


inline fun <T> T.also(block: (T) -> Unit): T {
    block(this)
    return this
}


inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
  • ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 객체λ₯Ό μ΄μ–΄μ§€λŠ” λΈ”λ‘μ˜ λ¦¬μ‹œλ²„λ‘œ 전달
  • λ¦¬μ‹œλ²„: λ°”λ‘œ μ΄μ–΄μ§€λŠ” 블둝 λ‚΄μ—μ„œ λ©”μ„œλ“œ 및 속성에 λ°”λ‘œ μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•  객체
  • 객체 자체λ₯Ό λ°˜ν™˜
  • ν™œμš©: νŠΉμ • 객체λ₯Ό μƒμ„±ν•˜λ©΄μ„œ ν•¨κ»˜ μ΄ˆκΈ°ν™”λ₯Ό ν•΄μ•Όν•  λ•Œ


inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}
  • ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 객체λ₯Ό μ΄μ–΄μ§€λŠ” λΈ”λ‘μ˜ 인자둜 λ„˜κΉ€
  • λΈ”λ‘μ˜ κ²°κ³Όκ°’ λ°˜ν™˜
  • ν™œμš©: ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•œ 객체λ₯Ό 인자둜 λ°›μœΌλ―€λ‘œ, 이λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‹€λ₯Έ λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜κ±°λ‚˜ 연산을 μˆ˜ν–‰ν•΄μ•Ό ν•˜λŠ” 경우


inline fun <T, R> T.run(block: T.() -> R): R {
    return block()
}
  • ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 객체λ₯Ό μ΄μ–΄μ§€λŠ” λΈ”λ‘μ˜ λ¦¬μ‹œλ²„λ‘œ 전달
  • λΈ”λ‘μ˜ κ²°κ³Όκ°’ λ°˜ν™˜
  • ν™œμš©: νŠΉμ • 객체의 λ©”μ„œλ“œλ‚˜ ν•„λ“œλ₯Ό μ—°μ†μ μœΌλ‘œ ν˜ΈμΆœν•˜κ±°λ‚˜ 값을 ν• λ‹Ήν•  λ•Œ μ‚¬μš©
  • apply()와 ν™œμš©μ΄ μœ μ‚¬ν•˜μ§€λ§Œ, apply()λŠ” μƒˆλ‘œμš΄ 객체λ₯Ό 생성함과 λ™μ‹œμ— μ—°μ†λœ μž‘μ—…μ΄ ν•„μš”ν•  λ•Œ μ‚¬μš©ν•˜κ³  run()은 이미 μƒμ„±λœ 객체에 μ—°μ†λœ μž‘μ—…μ΄ ν•„μš”ν•  λ•Œ μ‚¬μš©ν•œλ‹€λŠ” 점이 쑰금 λ‹€λ¦…λ‹ˆλ‹€.