Basic
코틀린 안드로이드 - 계산기 /다이얼로그 만들어보기
wdadaww
2022. 12. 6. 09:51
- layout
<?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=".MainActivity">
<View
android:id="@+id/toplayout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tablelayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_weight="1" />
<TextView
android:id="@+id/TextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:text=""
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</TextView>
<TextView
android:id="@+id/resultTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="15dp"
android:text=""
android:textSize="30sp"
app:layout_constraintBottom_toTopOf="@id/tablelayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
</TextView>
<TableLayout
android:id="@+id/tablelayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:paddingTop="21dp"
android:paddingBottom="0dp"
android:shrinkColumns="*"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toplayout"
app:layout_constraintVertical_weight="2.5">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5">
<Button
android:id="@+id/clearbutton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="clearButtonClick"
android:stateListAnimator="@null"
android:text="AC"
android:textSize="20sp">
</Button>
<Button
android:id="@+id/deleteButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="deleteButtonClick"
android:stateListAnimator="@null"
android:text="C"
android:textColor="@color/cardview_dark_background"
android:textSize="20sp">
</Button>
<Button
android:id="@+id/includbutton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="/"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/expandbutton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="X"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/invidebutton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="%"
android:textSize="30sp">
</Button>
</TableRow>
<TableRow android:layout_weight="1" />
<TableRow android:layout_weight="1">
<Button
android:id="@+id/button0"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:contentDescription="@string/app_name"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="0"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button9"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="9"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="8"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="7"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/minusbutton"
android:layout_width="wrap_content"
android:layout_height="85dp"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="-"
android:textSize="30sp">
</Button>
</TableRow>
<TableRow android:layout_weight="1">
<Button
android:id="@+id/button6"
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="6"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button5"
android:layout_width="62dp"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="5"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="4"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="3"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/plusbutton"
android:layout_width="wrap_content"
android:layout_height="90dp"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="+"
android:textSize="30sp">
</Button>
</TableRow>
<TableRow
android:id="@+id/text1"
android:layout_width="20dp"
android:layout_weight="1">
<Button
android:id="@+id/button1"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="1"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:stateListAnimator="@null"
android:text="2"
android:textSize="30sp">
</Button>
<Button
android:id="@+id/jumbutton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="buttonClick"
android:text="."
android:textSize="30sp">
</Button>
<Button
android:id="@+id/resultbutton"
android:layout_width="86dp"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:background="@drawable/button_background"
android:onClick="resultButtonClick"
android:text="="
android:textSize="50sp">
</Button>
</TableRow>
</TableLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
- Onclick View Bind
<Button
android:onClick="buttonclick."
buttonclick로 함수를 연결해준다. 액티비에서 onClickListener를 사용하지 않아도된다.
그럼 MainActivity에서
fun buttonclick(v: View) { 원하는 기능}
현재 View를 참조해서 함수를 만들수잇다. 이와같이 Button이 많을경우에 사용하면좋다.
when (v.id) {
R.id.button0 -> buttonClick("0")
R.id.button1 -> buttonClick("1")
R.id.button2 -> buttonClick("2")
R.id.button3 -> buttonClick("3")
R.id.button4 -> buttonClick("4")
R.id.button5 -> buttonClick("5")
R.id.button6 -> buttonClick("6")
R.id.button7 -> buttonClick("7")
R.id.button8 -> buttonClick("8")
R.id.button9 -> buttonClick("9")
R.id.plusbutton -> operatorButtonClick("+")
R.id.expandbutton -> operatorButtonClick("X")
R.id.includbutton -> operatorButtonClick("/")
R.id.minusbutton -> operatorButtonClick("-")
R.id.invidebutton -> operatorButtonClick("%")
R.id.jumbutton -> operatorButtonClick(".")
}
}
- MainActivity.kt
package com.example.part2chapter4
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.View.OnClickListener
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.example.part2chapter4.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
//뷰 바인딩 변수 선언
private var mainBinding: ActivityMainBinding? = null
private val binding get() = mainBinding!!
private val expreesionTextView: TextView by lazy {
findViewById(R.id.TextView)
}
private val resultTextView: TextView by lazy {
findViewById(R.id.resultTextView)
}
//계산식에 연산자가 있는지없는지 확인
private var haveOperator = false
//연산자를 사용하고있는지 확인
private var isOperator = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//oncreate생성
mainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
fun buttonClick(v: View) {
when (v.id) {
R.id.button0 -> buttonClick("0")
R.id.button1 -> buttonClick("1")
R.id.button2 -> buttonClick("2")
R.id.button3 -> buttonClick("3")
R.id.button4 -> buttonClick("4")
R.id.button5 -> buttonClick("5")
R.id.button6 -> buttonClick("6")
R.id.button7 -> buttonClick("7")
R.id.button8 -> buttonClick("8")
R.id.button9 -> buttonClick("9")
R.id.plusbutton -> operatorButtonClick("+")
R.id.expandbutton -> operatorButtonClick("X")
R.id.includbutton -> operatorButtonClick("/")
R.id.minusbutton -> operatorButtonClick("-")
R.id.invidebutton -> operatorButtonClick("%")
R.id.jumbutton -> operatorButtonClick(".")
}
}
private fun buttonClick(number: String) {
if (isOperator) {
expreesionTextView.append("")
}
isOperator = false
val expressionText = expreesionTextView.text.split(" ")
if (expressionText.isNotEmpty() && expressionText.last().length > 15) {
Toast.makeText(this, "15자리까지만사용할수있습니다", Toast.LENGTH_SHORT).show()
return
} else if (number == "0" && expressionText.last().isEmpty()) {
Toast.makeText(this, "0은 제일 앞에 올수 없습니다", Toast.LENGTH_SHORT).show()
}
expreesionTextView.append(number)
// TODO resulttextview실시간으로 계산결과를 넣음
binding.resultTextView.text = calculateExpression()
}
private fun operatorButtonClick(operator: String) {
if (expreesionTextView.text.isEmpty()) {
return
}
when {
haveOperator -> {
Toast.makeText(this, "연산자는 한번만 사용할수잇습니다.", Toast.LENGTH_SHORT).show()
return
}
else -> {
haveOperator = true
expreesionTextView.append(" $operator ")
}
}
}
fun resultButtonClick(v: View) {
val expressionTexts = expreesionTextView.text.split("")
if (expreesionTextView.text.isEmpty() || expressionTexts.size == 1) {
return
}
if (expressionTexts.size != 3 && haveOperator) {
Toast.makeText(this, "수식을 완성해주세요", Toast.LENGTH_SHORT).show()
return
}
if (expressionTexts[0].isNumber().not() || expressionTexts[2].isNumber().not()) {
Toast.makeText(this, "오류가 발생햇습니다", Toast.LENGTH_SHORT).show()
return
}
}
private fun calculateExpression(): String {
val expressionTexts = expreesionTextView.text.split(" ")
if (haveOperator.not() || expressionTexts.size != 3) {
return ""
} else if (expressionTexts[0].isNumber().not() || expressionTexts[2].isNumber().not()) {
return ""
}
val exp1 = expressionTexts[0].toBigInteger()
val exp2 = expressionTexts[2].toBigInteger()
val op = expressionTexts[1]
return when (op) {
"+" -> (exp1 + exp2).toString()
"X" -> (exp1 * exp2).toString()
"/" -> (exp1 / exp2).toString()
"-" -> (exp1 - exp2).toString()
"%" -> (exp1 % exp2).toString()
else -> " "
}
}
fun clearButtonClick(v: View) {
expreesionTextView.text = ""
resultTextView.text = ""
haveOperator = false
isOperator = false
}
private fun String.isNumber(): Boolean {
return try {
this.toBigInteger()
true
} catch (e: NumberFormatException) {
false
}
}
//알림창 띄우기
fun deleteButtonClick(view: View) {
AlertDialog.Builder(this).run {
setTitle("Test 계산기")
setIcon(android.R.drawable.ic_dialog_info)
setMessage("정말 종료하시겠습니까?")
setPositiveButton("OK", null)
setNegativeButton("Cancel", null)
setNeutralButton("More", null)
show()
}
}
}
- Text Drop
expreesionTextView.text = text.dropLast(1)
위와 같이 TextView의 text의 글자를 원하는 만큼 drop 할수있다.
- Spannable
Spannable은 텍스트에 부분적으로 효과를 적용할때 사용된다.
setSpan( 적용할 효과, 효과의 시작, 효과의 끝, 문자열 추가시 span값 적용 유뮤) 의 인자를 가지고있다.
효과
ForegroundColorSpan- 색깔
UnderlineSpan - 밑줄
AbsoluteSizeSpan - 텍스크 크기
효과지정 시작과끝 - 배열과같이 시작값은 0
마지막 인자 - span이 적용된 좌우측에 문자열이 추가될때 이 span값을 적용할 것인지 아닌지 정한다.
SPAN_EXCLUSIVE_EXCLUSIE : 왼쪽제거, 오른쪽 제거
SPAN_EXCLUSIVE_INCLUSIVE : 왼쪽 제거 오른쪽 포함
위처럼 EXCLUSIVE는 제거 , INCLUSIVE는포함으로 표현횐다.
확장함수
fun String.isNumber(): Boolean {}
이처럼 String객체를 확장하는 함수를 만들어줄 수가있다.
isNumber처럼 없는 기능을 만들어 볼수도 있고 여러가지 쓸수있을거같다.
- 애뮬레이터
- deletbuttonClick을이용해 알림창띄우기!
fun deleteButtonClick(view: View) {
AlertDialog.Builder(this).run {
setTitle("Test 계산기")
setIcon(android.R.drawable.ic_dialog_info)
setMessage("정말 종료하시겠습니까?")
setPositiveButton("OK", null)
setNegativeButton("Cancel", null)
setNeutralButton("More", null)
show()
}
}
- 버튼의 이벤트 핸들러등록
val eventHandler = object : DialogInterface.OnClickListener {
override fun onClick(p0: DialogInterface?, p1: Int) {
if (p1 == DialogInterface.BUTTON_POSITIVE) {
Log.d("hello", "YES BUTTON")
} else if (p1 == DialogInterface.BUTTON_NEGATIVE) {
Log.d("hello", "NO BUTTON")
} else if (p1 == DialogInterface.BUTTON_NEUTRAL) {
Log.d("hello", "MORE BUTTON")
}
}
}
setPositiveButton("YES", eventHandler)
setNegativeButton("NO", eventHandler)
setNeutralButton("MORE", eventHandler)
}
- 목록을 출력하는 알림창 띄우기
val items = arrayOf<String>("apple", "banana", "peach", "lemon", "orange")
AlertDialog.Builder(this).run {
setTitle("items test")
setIcon(android.R.drawable.ic_dialog_info)
setItems(items, object : DialogInterface.OnClickListener {
override fun onClick(p0: DialogInterface?, p1: Int) {
Log.d("hello", "Selected fruit : ${items[p1]}")
}
})
setPositiveButton("OK", null)
show()
}
}