Android-jetpack Compose

App 예제 : Calculator, Day of Birth - xml 사용

slow333 2023. 2. 9. 23:22

Calculator App

  • 전체적으로 복잡한 합수는 없으나, 로직이 좀 복잡함...
  • 숫자, 계산, =, - , clear, "."에 대한 별도의 함수를 구현해서 화면에 출력
  • 기타 기능 구현

activity_Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:padding="10dp"
        android:textSize="50sp"
        android:textColor="@color/black"
        android:background="@color/light_grey"
        android:id="@+id/tvInput"
        android:gravity="end|bottom"
    />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_weight="1"
        >
        <Button
            android:id="@+id/btn7"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="7"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText,NestedWeights"
            android:layout_margin="2dp"  />
        <Button
            android:id="@+id/btn8"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onDigit"
            android:text="8"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"  />
        <Button
            android:id="@+id/btn9"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="9"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"  />
        <Button
            android:id="@+id/btnDivide"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onOperator"
            android:text="/"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"  />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"    >
        <Button
            android:id="@+id/btn4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="4"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText,NestedWeights"
            android:layout_margin="2dp"  />
        <Button
            android:id="@+id/btn5"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="5"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"   />
        <Button
            android:id="@+id/btn6"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="6"
            android:onClick="onDigit"
            tools:ignore="HardcodedText"
            android:layout_margin="2dp"   />
        <Button
            android:id="@+id/btnMultiply"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="*"
            android:onClick="onOperator"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"    />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"    >
        <Button
            android:id="@+id/btn1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="1"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText,NestedWeights"
            android:layout_margin="2dp"   />
        <Button
            android:id="@+id/btn2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="2"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"   />
        <Button
            android:id="@+id/btn3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="3"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"   />
        <Button
            android:id="@+id/btnMinus"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="-"
            android:onClick="onOperator"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"        />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"    >
        <Button
            android:id="@+id/btn0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="0"
            android:onClick="onDigit"
            tools:ignore="ButtonStyle,HardcodedText,NestedWeights"
            android:layout_margin="2dp"    />
        <Button
            android:id="@+id/btnDot"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="."
            android:onClick="onDecimalPoint"
            tools:ignore="ButtonStyle,HardcodedText,NestedWeights"
            android:layout_margin="2dp"    />
        <Button
            android:id="@+id/btnClear"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="CLR"
            android:onClick="onClear"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"     />
        <Button
            android:id="@+id/butPlus"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="+"
            android:onClick="onOperator"
            tools:ignore="ButtonStyle,HardcodedText"
            android:layout_margin="2dp"     />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal"  >
        <Button
            android:id="@+id/btnEqual"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="="
            android:onClick="onEqual"
            android:layout_marginBottom="20dp"
            tools:ignore="HardcodedText,NestedWeights"
            android:layout_margin="2dp"     />
    </LinearLayout>

</LinearLayout>

MainActivity.kt

package kr.logcenter.mycalculator

import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.VisibleForTesting
import java.lang.ArithmeticException

class MainActivity : AppCompatActivity() {

   private var tvInput: TextView? = null
   private var lastNumeric : Boolean = false
   private var lastDot: Boolean = false

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      tvInput = findViewById(R.id.tvInput)
   }

   fun onDigit(view: View) {
      tvInput?.append((view as Button).text)
      lastNumeric = true
      lastDot = false
   }

   fun onClear(view: View) {
      tvInput?.text =""
      lastDot = false
      lastNumeric = false
   }
   fun onDecimalPoint(view: View) {
      if (lastNumeric && !lastDot) {
         tvInput?.append(".")
         lastNumeric = false
         lastDot = true
      }
   }

   fun onOperator(view: View) {
      tvInput?.text?.let {
         if (lastNumeric && !isOperatorAdded(it.toString())) {
            tvInput?.append((view as Button).text)
            lastNumeric = true
            lastDot = false
         }
      }
   }

   @SuppressLint("SetTextI18n")
   fun onEqual(view: View) {
      if (lastNumeric) {
         var tvValue = tvInput?.text.toString()
         var prefix = ""
         try {
            if (tvValue.startsWith("-")) {
               prefix ="-"
               tvValue =tvValue.substring(1)
            }
            if (tvValue.contains("-")) {
               val splitValue = tvValue.split("-")
               var one = splitValue[0]
               var two = splitValue[1]
               if (prefix.isNotBlank()) {
                  one = prefix + one
               }
               tvInput?.text = removeZeroAfterDot((one.toDouble() - two.toDouble()).toString())
            } else if (tvValue.contains("+")) {
               val splitValue = tvValue.split("+")
               var one = splitValue[0]
               var two = splitValue[1]
               if (prefix.isNotBlank()) {
                  one = prefix + one
               }
               tvInput?.text = removeZeroAfterDot((one.toDouble() + two.toDouble()).toString())
            }else if (tvValue.contains("*")) {
               val splitValue = tvValue.split("*")
               var one = splitValue[0]
               var two = splitValue[1]
               if (prefix.isNotBlank()) {
                  one = prefix + one
               }
               tvInput?.text = removeZeroAfterDot((one.toDouble() * two.toDouble()).toString())
            }else if (tvValue.contains("/")) {
               val splitValue = tvValue.split("/")
               var one = splitValue[0]
               var two = splitValue[1]
               if (prefix.isNotBlank()) {
                  one = prefix + one
               }
               tvInput?.text = removeZeroAfterDot((one.toDouble() / two.toDouble()).toString())
            }
         } catch (e: ArithmeticException) {
            e.printStackTrace()
            println("0으로 나누지 마세요")
         }
      }
   }

   private fun removeZeroAfterDot(result: String) : String {
      var value = result
      if(result.contains(".0")){
         value =result.substring(0, result.length - 2)
      }
      return value
   }

   private fun isOperatorAdded(value: String): Boolean {

      return if (value.startsWith("-")) {
         false
      } else {
         value.contains("/")
                 || value.contains("*")
                 || value.contains("+")
                 || value.contains("-")
      }
   }
}

==========================================================================

Day of Birth App

DatePickerDialog를 사용한 칼렌다 호출 후 데이터를 추출해서 계산하는 앱

데이터 저장 기능 없음... local storage ???

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:background="@color/bgColor"
    android:padding="16dp"
    tools:context=".MainActivity">
    <TextView
        android:text="Calculate My"
        android:textColor="@color/textBlue"
        android:textSize="34sp"
        android:layout_marginTop="16dp"
        android:padding="5dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/title"
        tools:ignore="HardcodedText"/>
    <TextView
        android:text="AGE IN Times and year"
        android:textColor="@color/white"
        android:padding="10dp"
        android:textSize="20sp"
        android:background="@color/black"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/age"
        tools:ignore="HardcodedText" android:textAllCaps="true"/>
    <Button
        android:text="SELECT DATE"
        android:backgroundTint="@color/btnBgColor"
        android:textColor="@color/white"
        android:textSize="26sp"
        android:textStyle="italic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="4dp"
        android:id="@+id/btnDate"/>
    <TextView
        android:text="1967.01.14"
        android:textColor="@color/textBlue"
        android:textSize="20sp"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tvSelectedDate"
        tools:ignore="HardcodedText"/>
    <TextView
        android:text="태어난 날"
        android:textColor="@color/lightGrey"
        android:textSize="20sp"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/var_date"
        tools:ignore="HardcodedText"/>
    <TextView
        android:text="1,400,000"
        android:textColor="@color/textBlue"
        android:textSize="26sp"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tvDiffMinutes"
        tools:ignore="HardcodedText"/>
    <TextView
        android:text="현재 까지 살은 시간"
        android:textColor="@color/lightGrey"
        android:textSize="20sp"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/txt_till_date"
        tools:ignore="HardcodedText"/>
    <TextView
        android:text="00년 00월 살음"
        android:textColor="@color/textBlue"
        android:textSize="26sp"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tvDiffYearMonth"
        tools:ignore="HardcodedText"/>
    <TextView
        android:text="아래 데이터 저장 추가 필요 나중에..."
        android:textColor="@color/material_on_primary_emphasis_high_type"
        android:textSize="14sp"
        android:layout_marginTop="16dp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tvMemo"
        tools:ignore="HardcodedText"/>
    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent" android:id="@+id/myData"/>

</LinearLayout>

MainActivity.kt

package kr.logcenter.dobcalc

import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.util.*

class MainActivity : AppCompatActivity() {

   private var tvSelectedDate: TextView? = null
   private var tvAgeInMinutes: TextView? = null
   private var tvDiffYear: TextView? = null

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      val btnDatePicker: Button = this.findViewById(R.id.btnDate)
      tvSelectedDate = findViewById(R.id.tvSelectedDate)
      tvAgeInMinutes = findViewById(R.id.tvDiffMinutes)
      tvDiffYear = findViewById(R.id.tvDiffYearMonth)

      btnDatePicker.setOnClickListener {
         clickDatePicker()
      }
   }

   @SuppressLint("NewApi", "SetTextI18n")
   private fun clickDatePicker() {

      val myCal = LocalDateTime.now()
      val year = myCal.year
      val month = myCal.month.value
      val day = myCal.dayOfMonth

      val dpd = DatePickerDialog(
         this,
         { _, selectedYear, selectedMonth, selectedDayOfMonth ->
            val selectedDate = "${selectedYear}/${selectedMonth + 1}/${selectedDayOfMonth}"
            tvSelectedDate?.text = selectedDate
            val sdf = SimpleDateFormat("yyyy/MM/dd", Locale.KOREAN)
            val theDate = sdf.parse(selectedDate)
            theDate?.let {
               val selectedDateInTimes = theDate.time / (60_000*60)
               val currentDate = sdf.parse(sdf.format(System.currentTimeMillis()))
               currentDate?.let {
                  val currentDateInTimes = currentDate.time / (60_000*60)
                  val differenceInTimes = currentDateInTimes - selectedDateInTimes
                  val df = DecimalFormat("#,###")
                  val dfDiff = df.format(differenceInTimes)
                  tvAgeInMinutes?.text = "${dfDiff.toString()}시간"
                  val diffInYear = differenceInTimes / 8760
                  val diffInMonth = (differenceInTimes%8760)/(24*30)
                  tvDiffYear?.text = "${diffInYear}년 ${diffInMonth}개월 살았군요!"
               }
            }
         },
         year, month, day
      )
      dpd.datePicker.maxDate = System.currentTimeMillis() - 86400000
      dpd.show()
   }
}