๋ณธ ์ปจ๋ฒค์ ๋ฌธ์๋ PRNDcompany/android-style-guide ์ Kotlin.md ๋ฐ Resource.md๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋์์ต๋๋ค.
- ๊ธฐ์กด ์ปจ๋ฒค์ ์ ์ง: ํ์ฌ ๋ฌธ์์ ๋ช ์๋ ๋ชจ๋ ๊ธฐ์กด ์ปจ๋ฒค์ ์ ์ด๋ ํ ๊ฒฝ์ฐ์๋ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ์ ๊ท ์ปจ๋ฒค์ ์ถ๊ฐ: ํ๋ก์ ํธ ์งํ ์ค ํ์ํ ๊ฒฝ์ฐ ์๋ก์ด ์ปจ๋ฒค์ ์ ๋ ผ์ํ๊ณ ๋ณธ ๋ฌธ์์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
if (a?.b?.isTraded ?: false)๋ฐฉ์๋ณด๋ค๋if (a?.b?.isTraded == true)์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ช ์์ ์ธ ๋น๊ต๋ฅผ ์ ํธํฉ๋๋ค.
- *ํ๋(Action)**์ ๋ํ๋ด๋ ๊ฐ๋
์ด๋ผ๋ฉด
function์ผ๋ก ์ ์ํฉ๋๋ค. -
์ฐธ์กฐ: Kotlin: should I define Function or Property?
*์ํ๋ ๊ฐ ๋ฑ ์ ๋ณด(State/Value)**๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฐ๋ ์ด๋ผ๋ฉด
custom accessor(์์ฑ)๋ก ์ ์ํฉ๋๋ค.
- package ์ด๋ฆ์ ์๋ฌธ์๋ก ์์ฑํฉ๋๋ค.
- ์์:
package kr.co.prnd.domain
- ์์:
- underscore(
_)๋ ์ฌ์ฉํ์ง ์์ต๋๋ค.//warning package kr.co.prnd.domain_module
- ์์ธ์ ์ผ๋ก ๋ถ๊ฐํผํ๊ฒ ์ฐ๊ฒฐ๋ ๋จ์ด๋ฅผ ๋ถ์ฌ์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ camelCase๋ก ์ฒ๋ฆฌํฉ๋๋ค.
- ์์:
package com.example.myProject
- ์์:
-
ViewModel์
observe()ํ ๋ ๋ชจ์ ๋๋ ํจ์ ์ด๋ฆ:setupXXX()
-
์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ฌ ๋ ํจ์ ์ด๋ฆ:
fetchXXX()
-
์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ํจ์ ์ด๋ฆ:
saveXXX()
-
Return ๊ฐ์ด ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ฌ ๋ ํจ์ ์ด๋ฆ:
getXXX()
-
ํน์ ๊ฐ์ฒด๋ฅผ ์ฐพ๋ ํจ์ ์ด๋ฆ:
findXXX()
-
๋ณต์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋๋ ๋ค์
s๋ฅผ ๋ถ์ ๋๋ค.getBrands()// OgetBrandList()// X
-
Raw ๊ฐ์ผ๋ก๋ถํฐ
enum์ ์ฐพ์ ๋ ํจ์ ์ด๋ฆ์find()๋ก ํฉ๋๋ค.enum class Color { RED, BLUE, GREEN; fun find(rawColor: String): Color = when (rawColor) { "red" -> RED "blue" -> BLUE "green" -> GREEN else -> throw IllegalArgumentException("invalid color: $rawColor") } }
function์ 1๊ฐ๋ง ๊ฐ์ง ๊ฒฝ์ฐ:fun interface OnXXXXListenerfunction์ 2๊ฐ ์ด์ ๊ฐ์ง ๊ฒฝ์ฐ:interface XXXListener
- Publisher(์ด๋ฒคํธ ๋ฐ์ ์ฃผ์ฒด)๊ฐ ์ด๋ฒคํธ๋ง ์ ๋ฌํ๊ณ Listener๊ฐ ์ ์ ์ธ ์ฑ ์์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํฉ๋๋ค.
- ์ด๋ฒคํธ๋ฅผ
handleํ๋ ์ฃผ์ฒด๊ฐlistenํ๊ณ ์๋ ๊ณณ์ผ ๋ ์ฌ์ฉํฉ๋๋ค.- ์์:
fun onClick(),fun onFocusChange(),fun onScrollChange(),fun onAnimationStart(),fun onTextChange()
- ์์:
- Publisher๊ฐ ๋ฌด์ธ๊ฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ Listener์๊ฒ ํด๋น ๋์์ด ์๋ฃ๋์์์ ์๋ฆด ๋ ์ฌ์ฉํฉ๋๋ค.
- ์ด๋ค ๋์์ ํ๊ณ ๋์ ์ด ๋์์ด ์ผ์ด๋ฌ์์ Listener์๊ฒ ์๋ ค์ค ๋ ์ฌ์ฉํฉ๋๋ค.
onEach(),doOnXXX()๊ฐ๋ ์ฒ๋ผ ํน์ ์ด๋ฒคํธ๋ฅผinterceptํด์ ์ธ ๋ ์ฌ์ฉํฉ๋๋ค.- ๋์์ ํ ๋ค์ Listener๋ฅผ ํธ์ถํด์ผ ๊ณผ๊ฑฐํ์ ์ด๋ฆ๊ณผ ์ผ์นํฉ๋๋ค.
- ์์:
fun onScrollStateChanged(),fun onTextChanged()
- ์์:
- Listener๋ฅผ ๊ตฌํํ๋ ๊ณณ์์ ๊ณผ๊ฑฐํ ์ฌ๋ถ์ ๋ฐ๋ผ, ํด๋น ์ด๋ฒคํธ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ๋์ง ๋ง์์ผ ํ๋์ง๋ฅผ ํ๋จํ ์ ์์ต๋๋ค.
- ์์ฑ์, ํจ์์์ Parameter๋ฅผ ์ ์ํ ๋ ํ ์ค๋ก ์ ์ ๊ฐ๋ฅํ๋ฉด ํ ์ค๋ก ์์ฑํฉ๋๋ค.
- ํ ์ค๋ก ์ ์ํ๊ธฐ ์ด๋ ต๋ค๋ฉด ๊ฐ parameter๋ณ๋ก ๊ฐํํฉ๋๋ค.
-
ํ ์ค์ ๋ค์ด๊ฐ๋
when๋ถ๊ธฐ๋ ์ค๊ดํธ({})๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.when (value) { 0 -> return // ... }
-
์ฌ๋ฌ ๊ฐ์ ์กฐ๊ฑด์ ๋์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
>๋ฅผ ํฌํจํ ๋ธ๋ก์ ๋ค์ ์ค๋ก ๋ด๋ ค์ ์์ฑํฉ๋๋ค.when (value) { foo -> // ... bar, baz -> return }
| WHAT Prefix | ์ค๋ช |
|---|---|
activity_ |
Activity์์ ์ฐ์ด๋ layout |
fragment_ |
Fragment์์ ์ฐ์ด๋ layout |
dialog_ |
Dialog์์ ์ฐ์ด๋ layout |
view_ |
CustomView์์ ์ฐ์ด๋ layout |
item_ |
RecyclerView, GridView, ListView ๋ฑ ViewHolder์ ์ฐ์ด๋ layout |
layout_ |
<include/>๋ก ์ฌ์ฌ์ฉ๋๋ ๊ณตํต์ layout |
- ์์:
activity_main.xml:MainActivity์ layoutfragment_request.xml:RequestFragment์ layoutdialog_contact.xml: ๋ฌธ์์๋ด Dialog์ layoutview_rating.xml: ์ปค์คํ ์ผ๋ก ๋ง๋RatingView์ layoutitem_my_car.xml: ๋ด ์ฐจ๋ ๋ชฉ๋ก์์ ์ฌ์ฉ๋๋ ๊ฐ๊ฐ์ item์ layoutlayout_dealer_review.xml: ์ฌ์ฌ์ฉ๋๋ ๋๋ฌ ๋ฆฌ๋ทฐ layout
-
View์ ๋๋ฌธ์๋ฅผ ์ถ์ฝํ์ฌ
<WHAT>์ Prefix๋ก ์ฌ์ฉํฉ๋๋ค. -
์๋ ์ด๋ฆ ๊ท์น์ ์ ์ฉํฉ๋๋ค.
-
Android์
View๋ CamelCase์ ๋๋ฌธ์๋ฅผ ์ถ์ฝํ ํํ๋ก ์ ํฉ๋๋ค.- ์์:
TextView->tv_
- ์์:
-
๋ง์ฝ
View์ ์ด๋ฆ์ดSpace,Switch์ ๊ฐ์ด 1๊ฐ์ ๋๋ฌธ์๋ง ์กด์ฌํ๋ค๋ฉด ๋ชจ๋ ์๋ฌธ์์ธ ์์ด๋๋ก ์ ํฉ๋๋ค.- ์์:
Switch->switch_
- ์์:
-
CustomView๋ ์ ์ฒด View์ ์ด๋ฆ์ snake_case ์ด๋ฆ์ผ๋ก ์ ํฉ๋๋ค.- ์์:
MyCustomView->my_custom_view - (๋ง์ฝ 1๊ฐ์ xml์ ๊ฐ์ ์ฌ๋ฌ
CustomView๊ฐ ์กด์ฌํ๋ค๋ฉด<WHAT>_<DESCRIPTION>์ ํํ๋ก ์ ํฉ๋๋ค.)
- ์์:
-
์๋ ํ์ ํด๋น View์ Prefix๊ฐ ์ ์๋์ด ์์ง ์๋ค๋ฉด ํ์์ ์์ํ์ฌ ์ด๋ฆ์ ์ ํ ๋ค ์ถ๊ฐํฉ๋๋ค.
View Prefix TextViewtv_ImageViewiv_CheckBoxcb_RecyclerViewrv_EditTextet_ProgressBarpb_FrameLayoutfl_NestedScrollViewnsv_Spacespace_Switchswitch_AbcDeFghadf_Abcdefabcdef_MyCustomViewmy_custom_viewYourViewyour_view
-
-
๊ธฐํ:
- ํด๋น View๋ฅผ ํน์ ๊ธฐ๋ฅ๊ณผ ์๊ด์์ด
VISIBLE/GONE๋ฑ์ View์ ์ฉ๋๋ก ์ฌ์ฉํ๋ค๋ฉดview_xxx๋ก ์ฌ์ฉํ๋ ๊ฒ๋ ํ์ฉํฉ๋๋ค. - ๋ฒํผ ๊ธฐ๋ฅ์ ์ํ View๋
ImageView,TextView๋ก๋ง ์ฌ์ฉํฉ๋๋ค. (Button,ImageButton์ ์กด์ฌ์ ์๋ฏธ๊ฐ ์์)
- ํด๋น View๋ฅผ ํน์ ๊ธฐ๋ฅ๊ณผ ์๊ด์์ด
-
์์:
iv_close: ๋ซ๊ธฐImageViewtv_select: ์ ํTextViewrv_car_list: ์๋์ฐจ ๋ชฉ๋กRecyclerViewview_etc_model: ๊ธฐํ ๋ชจ๋ธ ํ๋ฉดLinearLayout
- ์ด๋ฏธ์ง๊ฐ ์ฌ๋ฌ ๊ตฐ๋ฐ์์ ํ์ฉ๋ ๊ฒฝ์ฐ,
<WHERE>๋ ์๋ต ๊ฐ๋ฅํฉ๋๋ค. - ์ด๋ฏธ์ง์ ํฌ๊ธฐ๊ฐ 1๊ฐ๋ฐ์ ์๋ ๊ฒฝ์ฐ,
<SIZE>๋ ์๋ต ๊ฐ๋ฅํฉ๋๋ค.
| What Prefix | ์ค๋ช |
|---|---|
ic_ |
๋ฒํผ์ด ์๋ ํ๋ฉด์ ๋ณด์ฌ์ง๋ ์ด๋ฏธ์ง (์์ด์ฝ ํํ) |
bg_ |
๋ฒํผ์ด ์๋ ํ๋ฉด์ ๋ณด์ฌ์ง๋ ์ด๋ฏธ์ง (๋ฐฐ๊ฒฝ ํํ) |
img_ |
์ค์ ์ฌ์ง์ด๊ฑฐ๋ ์์ด์ฝ ํํ๊ฐ ์๋ ์ผ๋ฌ์คํธ ํํ์ ์ด๋ฏธ์ง |
div_ |
divider๋ก ํ์ฉ๋๋ ์ด๋ฏธ์ง |
- ๋ฐฐ๊ฒฝ์ด๋ ๋ฒํผ์์ View์ ์ํ์ ๋ฐ๋ผ drawable์ด ๋ณํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ด๋ฆ์ ์๋์ ๊ฐ์ต๋๋ค.
| ์ํ Suffix | ์ค๋ช |
|---|---|
_normal |
Normal ์ํ |
_pressed |
Pressed ์ํ |
_focused |
Focused ์ํ |
_disabled |
Disabled ์ํ |
_selected |
Selected ์ํ |
- ๋ฐฐ๊ฒฝ์์ด pressed ์ํ์ ๋ฐ๋ผ white -> sky_blue๋ก ๋ณํ๋ ๊ฒฝ์ฐ:
bg_white_to_sky_blue.xml - ๋ฐฐ๊ฒฝ์ด white ์์ 24dp๋ก ํ
๋๋ฆฌ๋ฅผ ๊ทธ๋ฆฌ๋ ๊ฒฝ์ฐ:
bg_white_radius_24dp.xml - ๋ฐฐ๊ฒฝ์ด ํฌ๋ช
ํ๋ฉฐ ๋ฐฐ๊ฒฝ์ ์ ๋ง์ sky_blue ์์ 8dp๋ก ํ
๋๋ฆฌ๋ฅผ ๊ทธ๋ฆฌ๋ ๊ฒฝ์ฐ:
bg_stroke_sky_blue_radius_8dp.xml
img_xxx์ ๊ฒฝ์ฐ ํ์ผ์ ํฌ๊ธฐ๊ฐ ํฐ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ฏ๋กtinypng์์ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์ธ ๋ค์ ์ถ๊ฐํด์ผ ํฉ๋๋ค. (GitHubimgbot์ ์ฌ์ฉํ๋ค๋ฉด ์๋ต ๊ฐ๋ฅ)- ๋๋ถ๋ถ ์ฉ๋์ด ํฐ ํ์ผ์ด์ด์
xxxhdpi์๋ง ๋ฃ์ต๋๋ค. - ์์:
btn_call_normal.png: ์ ํ ๊ฑธ๊ธฐ ๋ฒํผ ์ด๋ฏธ์งbtn_call_pressed.png: ์ ํ ๊ฑธ๊ธฐ ๋ฒํผ ๋๋ ธ์ ๋์ ์ด๋ฏธ์งbtn_call.xml: ์ ํ ๊ฑธ๊ธฐ ๋ฒํผ ์ด๋ฏธ์ง์ selector xmlic_dealer_gift.png: ๋๋ฌ๊ฐ ๋ณด๋ด์ค ๊ธฐํํฐ์ฝ์ ๋ณด์ฌ์ค ๋ ํ์๋๋ ์ด๋ฏธ์งimg_splash_chart.png: ์คํ๋์ ํ๋ฉด์์ ๋ณด์ฌ์ง๋ ์ฐจํธ ์ด๋ฏธ์ง
3.3.1. Dimension ์ด๋ฆ
- ์ฌ๋ฌ ๊ตฐ๋ฐ์์ ์ฌ์ฌ์ฉ๋๋ ๊ฐ๋
์ด๋ผ๋ฉด ๋ณ์๋ก ์ ์ํ์ฌ
@dimen/xxx์ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค. - ๊ทธ๋ ์ง ์๋ค๋ฉด ๋ช
์์ ์ผ๋ก
16dp์ ๊ฐ์ด XML ์ฝ๋์ ์ง์ ์์ฑํฉ๋๋ค.
- ๋๋ถ๋ถ์ margin/padding์ ์๋ ์ ์๋
space_xxx๋ก๋ง ์ฌ์ฉ๋๋๋ก ํฉ๋๋ค.<dimen name="space_small">12dp</dimen><dimen name="space_median">16dp</dimen><dimen name="space_s_large">18dp</dimen><dimen name="space_large">20dp</dimen><dimen name="space_x_large">24dp</dimen>
- ๊ทธ ์ธ์ ํน์ ํ๋ฉด์์ ์์ ๊ฐ์ ๋ฐ๋ฅด์ง ์๋ ๊ฒฝ์ฐ,
<WHERE>_<DESCRIPTION>_<WHAT>์ ๊ท์น์ผ๋ก ๋ง๋ญ๋๋ค.- ์์:
<dimen name="register_car_item_car_model_start_padding">40dp</dimen><dimen name="register_car_item_grade_start_padding">56dp</dimen><dimen name="register_car_item_car_detail_start_padding">72dp</dimen>
- ์์:
- 2๋ฒ ์ด์ ์ฐ์ด๋ ๊ฒฝ์ฐ๋
dimen์ ์ ์ํ๋ ๊ฒ์ ๊ฐ์ ํ๊ณ , 1๋ฒ๋ง ์ฐ์ด๋ ๊ฒฝ์ฐ์๋ XML ์ฝ๋์ ์ง์ ๋ฃ์ด๋ ๊ด์ฐฎ์ต๋๋ค.
- ๋์ด๋ง ์ง์ ํ ๋๋
height, 1:1 ๋น์จ๋ก ๊ฐ์ ๊ฐ์ด ๋ค์ด๊ฐ ๋๋size๋ก ํฉ๋๋ค.- ์์:
<dimen name="toolbar_height">56dp</dimen><dimen name="register_input_view_default_height">280dp</dimen><dimen name="register_input_view_collapse_height">200dp</dimen><dimen name="dealer_profile_image_size">48dp</dimen>
- ์์:
- ํน์ ํ๋ฉด์์ ์ฐ์ด๋ ํ
์คํธ๊ฐ ์๋๋ผ ์ฌ๋ฌ ๊ตฐ๋ฐ์์ ๊ณตํต์ผ๋ก ์ฌ์ฌ์ฉ๋ ํ
์คํธ๋ผ๋ฉด
all_<DESCRIPTION>์ผ๋ก ์ด๋ฆ์ ์ง์ต๋๋ค. - ์์:
permission_dialog_camera_title: ์นด๋ฉ๋ผ ๊ถํ์ ์๊ตฌํ๋ Dialog์ ์ ๋ชฉpermission_dialog_camera_description: ์นด๋ฉ๋ผ ๊ถํ์ ์๊ตฌํ๋ Dialog์ ์ค๋ช ๋ด์ฉall_yes: ๋คall_ok_understand: ์ฌ๋ฌ Dialog์์ ๋ค, ์๊ฒ ์ต๋๋ค๋ก ์ฐ์ด๋ ๊ณตํต์ ํ ์คํธ
-
๋ฌธ๋จ ํํ์ ๊ธด ๋ฌธ์์ด๋ก ๊ฐํ(
\n)์ด ํ์ํ ๊ฒฝ์ฐ,\n์ ๋ค์ ์ค์ ์์ ์๋๋ค.<string name="sample">๋ฌธ๋จ ์ฒซ๋ฒ์งธ์ค \\n๋ฌธ๋จ ๋๋ฒ์งธ์ค \\n๋ฌธ๋จ ์ธ๋ฒ์งธ์ค</string>
Theme๋themes.xml,Style์styles.xml์ ์ถ๊ฐํฉ๋๋ค.- 1๋ฒ๋ง ์ฐ์ด๋ ๊ฒฝ์ฐ์๋
style์ ๋ง๋ค์ง ์์ต๋๋ค. (๋จ, ์์ผ๋ก ์ฌ์ฌ์ฉ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ๊ฒฝ์ฐ์๋ ๊ฐ๋ฅ) - ๋ชจ๋
style์parent๋ฅผ ๊ฐ์ต๋๋ค.
-
style์ ์ด๋ฆ์parent์ ์ด๋ฆ ํจํด๊ณผ ๋ง์ถฅ๋๋ค.<style name="Widget.HeyDealer.Button" parent="@style/Widget.AppCompat.Button"> </style>
-
parent์์ ์ผ๋ถ ๋ด์ฉ๋ง ์์ ํ๊ณ ์ ํ๋ ๊ฒฝ์ฐ,parent์ด๋ฆ ๋ค์ ๋ฌ๋ผ์ง ๋ด์ฉ์ ๋ด์ฉ์ ์ถ๊ฐํด์ค๋๋ค.<style name="Theme.HeyDealer.Transparent" parent="Theme.HeyDealer"> </style>
-
Base Style๊ณผTheme์ ๊ฒฝ์ฐ๋ ์์Base๋ฅผ ๋ถ์ ๋๋ค.XML<style name="Base.Theme" parent="..." /> <style name="Base.Theme.Transparent">...</style> <style name="HeyDealerTheme" parent="Base.Theme">...</style> <style name="HeyDealerTheme.Transparent" parent="Base.Theme.Transparent" /> <style name="Base.TextAppearance.HeyDealer" parent="...">...</style> <style name="Base.TextAppearance.HeyDealer.Headline">...</style> <style name="TextAppearance.HeyDealer.Headline1" parent="Base.TextAppearance.HeyDealer.Headline">...</style> <style name="TextAppearance.HeyDealer.Headline2" parent="Base.TextAppearance.HeyDealer.Headline">...</style>
-
Attribute ์ด๋ฆ์ camelCase๋ก ํฉ๋๋ค.XML
<attr name="numStars" format="integer" />
-
๊ธฐ์กด์ ์ ์๋์ด ์๋
android:xxx์ ๊ฐ์ ๋์์ ์ ๋ํ๋ ๊ฒฝ์ฐ, ์ด ํ๊ทธ๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค.XML<declare-styleable name="SpannedGridLayoutManager"> <attr name="android:orientation" /> </declare-styleable>
android:xxxLeft/android:xxxRight๋์ **android:xxxStart/android:xxxEnd*๋ฅผ ์ฌ์ฉํฉ๋๋ค. (๋ชจ๋ Left/Right ์ฌ์ฉ ๋ถ๋ถ์ ์ ์ฉ)