Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

Kotlin์—์„œ ๊ฐ„๋‹จํ•œ ํŒ ๊ณ„์‚ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋” ์ •ํ™•ํžˆ ๋งํ•˜๋ฉด Kotlin 1.3.21, Android 4, Android Studio 3์ž…๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ๋Š” ์šฐ์„  Android ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ์—ฌ์ •์„ ์‹œ์ž‘ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํฅ๋ฏธ๋กœ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๋‚ด์—์„œ ๋ฌด์—‡์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ณ„์‚ฐ๊ธฐ๋Š” ์‹๋‹น์ด๋‚˜ ์นดํŽ˜์—์„œ ์‹œ๊ฐ„์„ ๋ณด๋‚ด๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ํšŒ์‚ฌ์˜ ํŒ ๊ธˆ์•ก์„ ๊ณ„์‚ฐํ•ด์•ผ ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์•„๋‹ˆ๊ณ  ํ•ญ์ƒ ์›จ์ดํ„ฐ๋ฅผ ์œ„ํ•ด ์ฐจ๋ฅผ ๋‚จ๊ธฐ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์„œ์–‘ ์ „ํ†ต์— ๊ฐ€๊น์ง€๋งŒ ๊ทธ๋Ÿฌํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ณผ์ •์€ ์–ด์จŒ๋“  ํฅ๋ฏธ ๋กญ์Šต๋‹ˆ๋‹ค.

์•Œ๋ฆผ: "Habr"์˜ ๋ชจ๋“  ๋…์ž๋ฅผ ์œ„ํ•œ - "Habr" ํ”„๋กœ๋ชจ์…˜ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Skillbox ๊ณผ์ •์— ๋“ฑ๋กํ•  ๋•Œ 10 ๋ฃจ๋ธ” ํ• ์ธ.

Skillbox๋Š” ๋‹ค์Œ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์‹ค๊ธฐ ์ฝ”์Šค "๋ชจ๋ฐ”์ผ ๊ฐœ๋ฐœ์ž PRO.

์•ฑ์ด ์‹คํ–‰ ์ค‘์ผ ๋•Œ์˜ ๋ชจ์Šต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

์ด์•ก์˜ ์›ํ•˜๋Š” ๋น„์œจ, ํšŒ์˜ ์ฐธ๊ฐ€์ž ์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค-๋‚จ์•„์•ผ ํ•  ํŒ์˜ ์–‘.

ะะฐั‡ะธะฝะฐะตะผ

์•ฑ์˜ ์ „์ฒด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

์ฒซ ๋ฒˆ์งธ ์กฐ์น˜ - ํ”„๋กœ์ ํŠธ ๋ฒ ์ด์Šค ๋‹ค์šด๋กœ๋“œ. Android Studio 3.0 ์ด์ƒ์—์„œ ์—ฝ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•˜๋ฉด ํฐ์ƒ‰ ํ™”๋ฉด์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ์ •์ƒ์ž…๋‹ˆ๋‹ค.

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

์‚ฌ์šฉ์ž ์ž‘์—…์€ ์‹œ๊ฐ„์ˆœ์œผ๋กœ ํ”„๋กœ์ ํŠธ์— ์ž‘์„ฑ๋˜๋ฏ€๋กœ ๋ชจ๋“  ๊ฒƒ์ด ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ณด๋ ค๋ฉด ๋ณด๊ธฐ -> ๋„๊ตฌ ์ฐฝ -> TODO๋ฅผ ์—ฝ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฐ๊ตฌํ•˜๊ณ  colors.xml์„ ์—ด์–ด ์ƒ‰์ƒ ํŒ”๋ ˆํŠธ๋ฅผ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. strings.xml์—๋Š” ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ(์บก์…˜)๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ณ  styles.xml์—๋Š” ์—ฌ๋Ÿฌ ๊ธ€๊ผด ํ…œํ”Œ๋ฆฟ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋น„์šฉ ์„น์…˜ ๊ฐœ๋ฐœ

activity_main.xml์„ ์—ด๊ณ  LinearLayout(#1)์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<TextView
    android_id="@+id/expensePerPersonTextView"
    android_layout_width="match_parent"
    android_layout_height="wrap_content"
    android_paddingTop="30dp"
    style="@style/h1Bold"
    android_textColor="@color/colorAccent"
    android_text="0"/>
 
<TextView
    android_layout_width="match_parent"
    android_layout_height="wrap_content"
    android_paddingBottom="25dp"
    style="@style/h2"
    android_textColor="@color/colorAccent"
    android_text="@string/perPersonStaticText"/>

์ด์ œ ๊ฐ’ ๋””๋ ‰ํ† ๋ฆฌ์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ‰์ƒ์„ ๊ฐ€์ง€๊ณ  ๋†€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. material.io ๋„๊ตฌ.

์ด์ œ ํ”„๋กœ์ ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?
๋ณด์‹œ๋‹ค์‹œํ”ผ ๋น„์šฉ ๊ณ„์‚ฐ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

๊ณ„์ • ์„น์…˜ ๊ฐœ๋ฐœ

๋น„์šฉ ์„น์…˜(#2) ๋‹ค์Œ์— LinearLayout์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

<LinearLayout
    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_orientation="vertical"
    android_background="@color/colorAccent">
 
<! โ€” TODO #3: Build Bill Section โ†’
 
โ€ฆ 
</LinearLayout>

TODO ๋ชฉ๋ก ๋‹ค์Œ์— LinearLayout์„ ๋‹ซ์€ ๋‹ค์Œ ์ƒˆ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ LinearLayout ์•ˆ์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค(#3).

<TextView
      android_layout_margin="15dp"
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_textColor="@color/colorWhite"
      style="@style/h4"
      android_text="@string/billStaticText"/>
 
<EditText
      android_id="@+id/billEditText"
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_textColor="@color/colorWhite"
      android_inputType="numberDecimal"
      android_maxLines="1"
      style="@style/h2Bold"
      android_text="0"/>

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์ฃผ์š” ์ž‘์—…์€ ์‹๋‹น ๋ชจ์ž„ ์ฐธ๊ฐ€์ž ๊ฐ๊ฐ์˜ ๊ฐœ๋ณ„ ๋น„์šฉ์„ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ costPerPersonTextView๊ฐ€ ์ฃผ์š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

EditText๋Š” ์ž…๋ ฅ์„ ํ•œ ์ค„๋กœ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค. ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” NumberDecimal inputType์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?
ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ „์ฒด ์†์ƒ ๋งค๊ฐœ๋ณ€์ˆ˜(๊นจ์ง„ ์ปต, ์ ‘์‹œ ๋“ฑ)๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

"์‚ฌ๋žŒ๊ณผ ํŒ" ์„น์…˜ ๊ฐœ๋ฐœ

ํŒ ๊ธˆ์•ก ์„ ํƒ๊ธฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ƒˆ LinearLayout ์„น์…˜(#4)์— ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”.

<TextView
      android_layout_margin="15dp"
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_textColor="@color/colorWhite"
      style="@style/h4"
      android_text="@string/tipStaticText"/>
 
<LinearLayout
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_orientation="horizontal">
 
<ImageButton
        android_id="@+id/subtractTipButton"
        style="@style/operationButton"
        android_layout_marginLeft="20dp"
        android_layout_marginStart="20dp"
        android_src="@drawable/subtract"/>
 
<TextView
        android_id="@+id/tipTextView"
        android_layout_margin="15dp"
        android_layout_width="0dp"
        android_layout_height="wrap_content"
        android_textColor="@color/colorWhite"
        android_layout_weight="1"
        style="@style/h2Bold"
        android_text="20%"/>
 
<ImageButton
        android_id="@+id/addTipButton"
        style="@style/operationButton"
        android_layout_marginEnd="20dp"
        android_layout_marginRight="20dp"
        android_src="@drawable/add"/>
 
</LinearLayout>

์ด ์ฝ”๋“œ๋Š” ํŒ ๊ธˆ์•ก์„ ์ •ํ™•ํ•˜๊ฒŒ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ํ…์ŠคํŠธ ๊ฐ’์€ 20์ž…๋‹ˆ๋‹ค. ImageButton์—๋Š” ์“ฐ๊ธฐ ๊ถŒํ•œ์ด ์žˆ๋Š” ํด๋”์˜ ์•„์ด์ฝ˜์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์ „์ฒด ์„น์…˜์„ ๋ณต์‚ฌํ•˜๊ณ  ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(#5).

  • ImageButton ID(subtractPeopleButton, addPeopleButton)
  • TextView ID(numberOfPeopleStaticText, numberOfPeopleTextView)
  • numberOfPeopleTextView์˜ DefaultText(4์—ฌ์•ผ ํ•จ).

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

์ด์ œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•  ๋•Œ ์ธ๋ณด์ด์Šค ๊ธˆ์•ก์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ณ  ์ถ”๊ฐ€/๋นผ๊ธฐ ๋ฒ„ํŠผ๋„ ์ž‘๋™ํ•˜์ง€๋งŒ ์ง€๊ธˆ๊นŒ์ง€๋Š” ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ณด๊ธฐ ์ถ”๊ฐ€

MainActivity.kt๋ฅผ ์—ด๊ณ  initViews ํ•จ์ˆ˜(#6)์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

private fun initViews() {
        expensePerPersonTextView = findViewById(R.id.expensePerPersonTextView)
        billEditText = findViewById(R.id.billEditText)
 
addTipButton = findViewById(R.id.addTipButton)
        tipTextView = findViewById(R.id.tipTextView)
        subtractTipButton = findViewById(R.id.subtractTipButton)
 
addPeopleButton = findViewById(R.id.addPeopleButton)
        numberOfPeopleTextView = findViewById(R.id.numberOfPeopleTextView)
        subtractPeopleButton = findViewById(R.id.subtractPeopleButton)
 
//TODO #8: Bind Buttons to Listener
 
//TODO #16: Bind EditText to TextWatcher
 
}

๋ฒ„ํŠผ ๋งˆ๋ฌด๋ฆฌ

๋ฒ„ํŠผ ํด๋ฆญ์— ๋Œ€ํ•œ ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ํด๋ž˜์Šค ์ˆ˜์ค€(#7)์—์„œ View.OnClickListener๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

ํด๋ž˜์Šค MainActivity: AppCompatActivity(), View.OnClickListener {

์ง€๊ธˆ ๋ฐ”๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฒƒ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ๋‹จ๊ณ„๋ฅผ ๋” ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(# 8).

override fun onClick(v: View?) {
        when (v?.id) {
            R.id.addTipButton -> incrementTip()
            R.id.subtractTipButton -> decrementTip()
            R.id.addPeopleButton -> incrementPeople()
            R.id.subtractPeopleButton -> decrementPeople()
        }
    }

๋ฒ„ํŠผ๊ณผ ์Šค์œ„์น˜ ์ธก๋ฉด์—์„œ Kotlin์€ ๋ชจ๋“  ๊ฒƒ์„ ๋งค์šฐ ๋ฉ‹์ง€๊ฒŒ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค! ๋ชจ๋“  ์ฆ๊ฐ€ ๋ฐ ๊ฐ์†Œ ํ•จ์ˆ˜์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.
(#9 โ€“#12):

private fun incrementTip() {
        if (tipPercent != MAX_TIP) {
            tipPercent += TIP_INCREMENT_PERCENT
            tipTextView.text = String.format("%d%%", tipPercent)
        }
    }
 
private fun decrementTip() {
        if (tipPercent != MIN_TIP) {
            tipPercent -= TIP_INCREMENT_PERCENT
            tipTextView.text = String.format("%d%%", tipPercent)
        }
    }
 
private fun incrementPeople() {
        if (numberOfPeople != MAX_PEOPLE) {
            numberOfPeople += PEOPLE_INCREMENT_VALUE
            numberOfPeopleTextView.text = numberOfPeople.toString()
        }
    }
 
private fun decrementPeople() {
        if (numberOfPeople != MIN_PEOPLE) {
            numberOfPeople -= PEOPLE_INCREMENT_VALUE
            numberOfPeopleTextView.text = numberOfPeople.toString()
        }
    }

์—ฌ๊ธฐ์„œ ์ฝ”๋“œ๋Š” ์ตœ๋Œ€๊ฐ’(MAX_TIP & MAX_PEOPLE)์œผ๋กœ ์ฆ๋ถ„ ํ•จ์ˆ˜๋ฅผ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ฝ”๋“œ๋Š” ์ตœ์†Œ๊ฐ’(MIN_TIP & MIN_PEOPLE)์œผ๋กœ ๊ฐ์†Œ ํ•จ์ˆ˜๋ฅผ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ initViews ํ•จ์ˆ˜(#13)์—์„œ ๋ฒ„ํŠผ์„ ๋ฆฌ์Šค๋„ˆ์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค.

private fun initViews() {
 
...
 
addTipButton.setOnClickListener(this)
        subtractTipButton.setOnClickListener(this)
 
addPeopleButton.setOnClickListener(this)
        subtractPeopleButton.setOnClickListener(this)
 
//TODO #15: Bind EditText to TextWatcher
}

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

์ด์ œ ์ด ํ”ผํ•ด, ํŒ ๋ฐ ํšŒ์˜ ์ฐธ๊ฐ€์ž ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž, ์ด์ œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€...

๋น„์šฉ ์„น์…˜

์ด ์ฝ”๋“œ๋Š” ๋น„์šฉ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค(#14).

private fun calculateExpense() {
 
val totalBill = billEditText.text.toString().toDouble()
 
val totalExpense = ((HUNDRED_PERCENT + tipPercent) / HUNDRED_PERCENT) * totalBill
        val individualExpense = totalExpense / numberOfPeople
 
expensePerPersonTextView.text = String.format("$%.2f", individualExpense)
 
}

์Œ, ์—ฌ๊ธฐ ํšŒ์‚ฌ์˜ ์ธ์›์ˆ˜๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ํŒ์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค(#15).

private fun incrementTip() {
 
โ€ฆ
 
}
 
private fun decrementTip() {
 
โ€ฆ
 
}
 
private fun incrementPeople() {
 
โ€ฆ
 
}
 
private fun decrementPeople() {
 
โ€ฆ
 
}

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ž˜ ๋ณด์ด๊ณ  ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋” ๋‚˜์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒญ๊ตฌ ๊ธˆ์•ก์„ ์‚ญ์ œํ•œ ํ›„ ํžŒํŠธ๋‚˜ ์นœ๊ตฌ ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๋ ค๊ณ  ํ•˜๋ฉด ์•„์ง ๋น„์šฉ ์ œ๋กœ์— ๋Œ€ํ•œ ํ™•์ธ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์ด ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ธ๋ณด์ด์Šค ๊ธˆ์•ก์„ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์š”๊ธˆ์ด ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ตœ์ข… ๋‹จ๊ณ„

TextWatcher ์ถ”๊ฐ€(#16):

ํด๋ž˜์Šค MainActivity: AppCompatActivity(), View.OnClickListener, TextWatcher {

๊ทธ๋Ÿฐ ๋‹ค์Œ billEditText ๋ฆฌ์Šค๋„ˆ(#17)๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

billEditText.addTextChangedListener(์ด)

๋˜ํ•œ TextWatcher๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(#18).

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        if (!billEditText.text.isEmpty()) {
            calculateExpense()
        }
    }
override fun afterTextChanged(s: Editable?) {}

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค! ์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค. Kotlin์œผ๋กœ ์ž์‹ ๋งŒ์˜ "ํŒ ๊ณ„์‚ฐ๊ธฐ"๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

Kotlin์œผ๋กœ ํŒ ๊ณ„์‚ฐ๊ธฐ ๋นŒ๋“œ: ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”?

Skillbox๋Š” ๋‹ค์Œ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€