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>
'안드로이드 앱(Kotlin|Java) > [2025~] 안드로이드 앱' 카테고리의 다른 글
Part1_Ch05_05 계산기 UI 꾸미기 (0) | 2025.04.09 |
---|---|
Part1_Ch05_04 계산 기능 구현하기(2) (0) | 2025.04.09 |
Part1_Ch05_02 계산기 UI 그리기 (0) | 2025.04.09 |
Part1_Ch05_01 개요 및 학습목표 (0) | 2025.04.09 |
Part1_Ch04_09 복습 및 한걸음 더 (1) | 2025.04.09 |