1) 수식창과 결과창 UI

키패드 위의 버튼을 눌렀을 때 입력값이 나오는 수식창과 결과창을 UI 로 그려보자.

activity_main.xml

<TextView
        android:id="@+id/equationTextView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="equation"
        android:gravity="end"
        android:textSize="30sp"
        android:padding="16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/resultTextView"
        />

    <TextView
        android:id="@+id/resultTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="result"
        android:gravity="end"
        android:padding="16dp"
        android:textSize="36sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@id/keyPadFlow"/>

2) 기능 구현

2-1) gradle : app

    viewBinding {
        enabled = true
    }

2-2) MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding
    private val firstNumberText = StringBuilder("")
    private val secondNumberText = StringBuilder("")
    private val operatorText = StringBuilder("")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
}

값이 많이 변경될 때는 StringBuilder 를 사용하는 것이 효과적이다.


2-3) activity_main.xml

이전 실습과 다르게, 코틀린 파일에서 setonClickListener 를 사용하는 대신

xml 파일에서 onClick 을 지정해보자.

줄이 그어져 있는 것은, deprecated, 즉 언젠가 없어질 요소라는 의미이다.

그러나 여전히 onClick 은 자주 사용되는 요소이므로 학습해보자.

 

 

activity_main.xml

    <Button
		    ...
        android:id="@+id/button1"
        android:text="1"
        android:onClick="numberClicked"
        ... />

android:onClick="numberClicked"


2-4) MainActivity.kt

숫자, 연산자, clear, equal 버튼 클릭 시

동작시킬 함수를 각각 구현해보자.

numberClicked

fun numberClicked(view : View) {
    // Log.d("numberClicked", "one")
    // button 에서 누른 숫자 추출
    // 모든 view 가 text 라는 attribute 를 가지고 있지 않다.
    // view 가 버튼이라면, text를 string 으로 변환
    // view 가 Null 이 아니면, text 값을 받아 string 형으로 변환
    // 버튼이 아니면 빈문자열 ""
    val numberString = (view as? Button)?.text?.toString() ?: ""

    // 첫 번째 숫자일지, 두 번째 숫자일지 확인
    // 첫 번째 숫자와 연산자가 없으면, 첫 번째 숫자
    val numberText = if(operatorText.isEmpty()) firstNumberText else secondNumberText

    numberText.append(numberString)

    // ui 업데이트
    updateEquationTextView()
}

 

 

fun numberClicked(view : View)

xml 에서 접근할 수 있어야 하므로, public 으로 지정

매개변수를 View 로 받으므로, 반드시 매개변수 쓰기

 

 

clearClicked

fun clearClicked(view : View) {
        firstNumberText.clear()
        secondNumberText.clear()
        operatorText.clear()
        updateEquationTextView() // ui 업데이트
        binding.resultTextView.text =""
    }

 

 

equalClicked

fun equalClicked(view : View) {
    if(firstNumberText.isEmpty() || secondNumberText.isEmpty() || operatorText.isEmpty()) {
        Toast.makeText(this, "올바르지 않은 수식 입니다.", Toast.LENGTH_SHORT).show()
        return
    }
    val firstNumber = firstNumberText.toString().toInt()
    val secondNumber = secondNumberText.toString().toInt()

    val result = when(operatorText.toString()){
        "+" -> firstNumber + secondNumber
        "-" -> firstNumber - secondNumber
        else -> "잘못된 수식 입니다."
    }.toString() // 한 번에 toString() 으로 받기
    binding.resultTextView.text = result

    updateEquationTextView()
}

 

 

operatorClicked

fun operatorClicked(view : View) {
    val operatorString = (view as? Button)?.text?.toString() ?: ""

    // 첫 번째 숫자를 입력받지 못하면,
    if(firstNumberText.isEmpty()) {
        Toast.makeText(this, "먼저 숫자를 입력해주세요.", Toast.LENGTH_SHORT).show()
        return
    }

    // 두 번째 숫자까지 입력받았으면,
    if(secondNumberText.isNotEmpty()){
        Toast.makeText(this, "1개의 연산자에 대해서만 연산이 가능합니다.", Toast.LENGTH_SHORT).show()
        return
    }

    operatorText.append(operatorString)
    updateEquationTextView() // ui 업데이트
}

 

 

ui업데이트함수

// ui 업데이트 함수
private fun updateEquationTextView() {
    binding.equationTextView.text = "$firstNumberText $operatorText $secondNumberText"
}

3) 전체코드

MainActivity.kt

package com.part1.chapter5

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.part1.chapter5.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding
    private val firstNumberText = StringBuilder("")
    private val secondNumberText = StringBuilder("")
    private val operatorText = StringBuilder("")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }

    // xml 에서 접근할 수 있어야 하므로, public 으로 지정
    // 매개변수를 View 로 받으므로, 반드시 매개변수 쓰기
    fun numberClicked(view : View) {
        // Log.d("numberClicked", "one")
        // button 에서 누른 숫자 추출
        // 모든 view 가 text 라는 attribute 를 가지고 있지 않다.
        // view 가 버튼이라면, text를 string 으로 변환
        // view 가 Null 이 아니면, text 값을 받아 string 형으로 변환
        // 버튼이 아니면 빈문자열 ""
        val numberString = (view as? Button)?.text?.toString() ?: ""

        // 첫 번째 숫자일지, 두 번째 숫자일지 확인
        // 첫 번째 숫자와 연산자가 없으면, 첫 번째 숫자
        val numberText = if(operatorText.isEmpty()) firstNumberText else secondNumberText

        numberText.append(numberString)

        // ui 업데이트
        updateEquationTextView()
    }

    fun clearClicked(view : View) {
        firstNumberText.clear()
        secondNumberText.clear()
        operatorText.clear()
        updateEquationTextView() // ui 업데이트
        binding.resultTextView.text =""
    }

    fun equalClicked(view : View) {
        if(firstNumberText.isEmpty() || secondNumberText.isEmpty() || operatorText.isEmpty()) {
            Toast.makeText(this, "올바르지 않은 수식 입니다.", Toast.LENGTH_SHORT).show()
            return
        }
        val firstNumber = firstNumberText.toString().toInt()
        val secondNumber = secondNumberText.toString().toInt()

        val result = when(operatorText.toString()){
            "+" -> firstNumber + secondNumber
            "-" -> firstNumber - secondNumber
            else -> "잘못된 수식 입니다."
        }.toString() // 한 번에 toString() 으로 받기
        binding.resultTextView.text = result

        updateEquationTextView()
    }

    fun operatorClicked(view : View) {
        val operatorString = (view as? Button)?.text?.toString() ?: ""

        // 첫 번째 숫자를 입력받지 못하면,
        if(firstNumberText.isEmpty()) {
            Toast.makeText(this, "먼저 숫자를 입력해주세요.", Toast.LENGTH_SHORT).show()
            return
        }

        // 두 번째 숫자까지 입력받았으면,
        if(secondNumberText.isNotEmpty()){
            Toast.makeText(this, "1개의 연산자에 대해서만 연산이 가능합니다.", Toast.LENGTH_SHORT).show()
            return
        }

        operatorText.append(operatorString)
        updateEquationTextView() // ui 업데이트
    }

    // ui 업데이트 함수
    private fun updateEquationTextView() {
        binding.equationTextView.text = "$firstNumberText $operatorText $secondNumberText"
    }

}

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.part1.chapter5.MainActivity">

    <TextView
        android:id="@+id/equationTextView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="equation"
        android:gravity="end"
        android:textSize="30sp"
        android:padding="16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/resultTextView"
        />

    <TextView
        android:id="@+id/resultTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="result"
        android:gravity="end"
        android:padding="16dp"
        android:textSize="36sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@id/keyPadFlow"/>



    <!-- Flow -->
    <androidx.constraintlayout.helper.widget.Flow
        android:id="@+id/keyPadFlow"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHeight_percent="0.7"
        app:layout_constraintVertical_bias="1"
        app:flow_maxElementsWrap="4"
        app:flow_wrapMode="chain"
        android:padding="8dp"
        app:flow_horizontalGap="8dp"
        app:constraint_referenced_ids="button1, button2, button3, buttonClear, button4, button5, button6, buttonPlus, button7, button8, button9, buttonMinus
        ,button0, buttonEqual"
        />


    <Button
        android:id="@+id/button1"
        style="@style/numKeyPad"
        android:text="1"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints"/>

    <Button
        android:id="@+id/button2"
        style="@style/numKeyPad"
        android:text="2"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button3"
        style="@style/numKeyPad"
        android:text="3"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button4"
        style="@style/numKeyPad"
        android:text="4"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints"/>

    <Button
        android:id="@+id/button5"
        style="@style/numKeyPad"
        android:text="5"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button6"
        style="@style/numKeyPad"
        android:text="6"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button7"
        style="@style/numKeyPad"
        android:text="7"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints"/>

    <Button
        android:id="@+id/button8"
        style="@style/numKeyPad"
        android:text="8"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button9"
        style="@style/numKeyPad"
        android:text="9"
        android:onClick="numberClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/button0"
        style="@style/numKeyPad"
        android:text="0"
        android:onClick="numberClicked"
        app:layout_constraintHorizontal_weight="1"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/buttonEqual"
        style="@style/operatorKeypad"
        android:text="="
        android:onClick="equalClicked"
        app:layout_constraintHorizontal_weight="3"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/buttonClear"
        style="@style/operatorKeypad"
        android:text="C"
        android:onClick="clearClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/buttonPlus"
        style="@style/operatorKeypad"
        android:text="+"
        android:onClick="operatorClicked"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/buttonMinus"
        style="@style/operatorKeypad"
        android:text="-"
        android:onClick="operatorClicked"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

+ Recent posts