【初心者がAndroid Studio+kotlinで電卓アプリを作ってみる】第9回:数字ボタンをすべて作る編

kotlinで電卓アプリ作成

電卓アプリを作ってみるシリーズ一覧はこちらをクリック

今回のポイント

いま1、2、3ボタンしかないので数字ボタンを全部作っていきたいと思っています。

activity_main.xmlを編集してボタンを作る

現在のactivity_main.xml

必要なボタンは0,4,5,6,7,8,9の7個ですのでButtonをドラッグアンドドロップして7個適当な位置に追加しました。

id,layout_height,insetLeft,insetRight,text,textSizeを変更しました。
忘れた人はその5を見て下さい。

Strings.xmlはこんな感じになってます。

<resources>
    <string name="app_name">CalculatorApplication</string>
    <string name="text_button_Zero">0</string>追加
    <string name="text_button_one">1</string>
    <string name="text_button_two">2</string>
    <string name="text_button_three">3</string>
    <string name="text_button_four">4</string>追加
    <string name="text_button_five">5</string>追加
    <string name="text_button_six">6</string>追加
    <string name="text_button_seven">7</string>追加
    <string name="text_button_eight">8</string>追加
    <string name="text_button_nine">9</string>追加
    <string name="text_button_addition">+</string>
    <string name="text_button_Subtraction">-</string>
    <string name="text_button_Multiplication">×</string>
    <string name="text_button_Division">÷</string>
    <string name="text_button_equal">=</string>
    <string name="text_button_ac">AC</string>
</resources>

buttonの位置を変える

前回までで作ったボタンの位置情報をクリアにしちゃいます。
Component Treeのボタンを全て選択して右クリック→Clear Constraints of Selectionをクリック
(textViewは選択していません)
全てのボタンが位置情報ないよのエラーが出ました。

適当に位置をいじってこんな感じになりました。
まあxmlはエラーさえ出てなければプログラムには影響ないので適当でいいか、また変更しそうだし。

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=".MainActivity">
    <TextView
        android:id="@+id/textViewValuedisplay"
        android:layout_width="0dp"
        android:layout_height="80dp"
        android:background="@android:drawable/edit_text"
        android:textAlignment="viewEnd"
        android:textSize="60sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <Button
        android:id="@+id/buttonNine"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_nine"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/buttonEight"
        app:layout_constraintTop_toTopOf="@+id/buttonEight" />
    <Button
        android:id="@+id/buttonTwo"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_two"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/buttonOne"
        app:layout_constraintTop_toTopOf="@+id/buttonOne" />
    <Button
        android:id="@+id/buttonSeven"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_marginStart="16dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_seven"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonFour"
        app:layout_constraintStart_toStartOf="parent" />
    <Button
        android:id="@+id/buttonEqual"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_equal"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <Button
        android:id="@+id/buttonSubtraction"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_Subtraction"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonAddition"
        app:layout_constraintEnd_toEndOf="parent" />
    <Button
        android:id="@+id/buttonFive"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_five"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/buttonFour"
        app:layout_constraintTop_toTopOf="@+id/buttonFour" />
    <Button
        android:id="@+id/buttonEight"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_eight"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/buttonSeven"
        app:layout_constraintTop_toTopOf="@+id/buttonSeven" />
    <Button
        android:id="@+id/buttonAddition"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_addition"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonEqual"
        app:layout_constraintEnd_toEndOf="parent" />
    <Button
        android:id="@+id/buttonZero"
        android:layout_width="176dp"
        android:layout_height="80dp"
        android:layout_marginStart="16dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_Zero"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
    <Button
        android:id="@+id/buttonFour"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_marginStart="16dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_four"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonOne"
        app:layout_constraintStart_toStartOf="parent" />
    <Button
        android:id="@+id/buttonOne"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_marginStart="16dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_one"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonZero"
        app:layout_constraintStart_toStartOf="parent" />
    <Button
        android:id="@+id/buttonDivision"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_Division"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonMultiplication"
        app:layout_constraintEnd_toEndOf="parent" />
    <Button
        android:id="@+id/buttonSix"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_six"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/buttonFive"
        app:layout_constraintTop_toTopOf="@+id/buttonFive" />
    <Button
        android:id="@+id/buttonAllClear"
        android:layout_width="176dp"
        android:layout_height="80dp"
        android:layout_marginStart="16dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_ac"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonSeven"
        app:layout_constraintStart_toStartOf="parent" />
    <Button
        android:id="@+id/buttonThree"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_three"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@+id/buttonTwo"
        app:layout_constraintTop_toTopOf="@+id/buttonTwo" />
    <Button
        android:id="@+id/buttonMultiplication"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:insetLeft="6dp"
        android:insetRight="6dp"
        android:text="@string/text_button_Multiplication"
        android:textSize="24sp"
        app:layout_constraintBottom_toTopOf="@+id/buttonSubtraction"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

ボタン押下時の処理を追加する

Activity_Main.ktを開いて0ボタン、4から9ボタンの処理を追加してみます。
画像では5ボタン押下時の処理までしか写っていませんが6,7,8ボタンも同様。
コピペしてちょちょっと変更してみます。変更箇所に赤〇を付けておきます。
コピペだと変更箇所を忘れてしまって思い通りの処理にならないイージーなミスがありがちなので確認をしっかりする(自分への戒めです)

        // 0ボタンが押された時
        binding.buttonZero.setOnClickListener {
            valueForTempStorage = valueForTempStorage * 10 + 0
            binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
        }

長いのでまた関数を作ってみよう

違いはここだけなのでまとめてしまいたいと思っています。
関数名は数字(Numbers)タップした(Tapped)でいいか。
その8でoperatorTapped()関数を作った時と同じように
numbersTapped()関数を作って中身は// 0ボタンが押された時の内容をコピペ

呼び出される側の関数

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped() {
            valueForTempStorage = valueForTempStorage * 10 + 0
            binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
        }

呼び出す側の記述

        // 0ボタンが押された時
        binding.buttonZero.setOnClickListener {
            numbersTapped()
        }

これを// 1ボタンが押された時、// 2ボタンが押された時、// 3ボタンが…に適用していきたいのですが、関数内の
valueForTempStorage = valueForTempStorage * 10 + 0
の+0、+1、+2をif,else ifで分岐するとこうなってしまってすっきりしないので引数というものを使ってみたい。

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped() {
            if (valueForTempStorage == 0.0) {
                valueForTempStorage = valueForTempStorage * 10 + 0
            }
            else if (valueForTempStorage == 1.0) {
                valueForTempStorage = valueForTempStorage * 10 + 1
            }
            else if (valueForTempStorage == 2.0) {
                valueForTempStorage = valueForTempStorage * 10 + 2
            }
            else if (valueForTempStorage == 3.0) {
                valueForTempStorage = valueForTempStorage * 10 + 3
            }
            else if (valueForTempStorage == 4.0) {
                valueForTempStorage = valueForTempStorage * 10 + 4
            }
            else if (valueForTempStorage == 5.0) {
                valueForTempStorage = valueForTempStorage * 10 + 5
            }
            else if (valueForTempStorage == 6.0) {
                valueForTempStorage = valueForTempStorage * 10 + 6
            }
            else if (valueForTempStorage == 7.0) {
                valueForTempStorage = valueForTempStorage * 10 + 7
            }
            else if (valueForTempStorage == 8.0) {
                valueForTempStorage = valueForTempStorage * 10 + 8
            }
            else if (valueForTempStorage == 9.0) {
                valueForTempStorage = valueForTempStorage * 10 + 9
            }
            binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
        }

関数の引数を使ってみる

関数の()内に引数を追加してみました。

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(nambers : Int) {

さらに引数のnambersを数字のところに設定します。

変更前
valueForTempStorage = valueForTempStorage * 10 + 0
変更後
valueForTempStorage = valueForTempStorage * 10 + nambers

呼び出し側の()内に(0)を入れて送ると関数のnambersに0が入るみたいな感じだろうと思う。
あとは呼び出し側の// 1ボタンが押された時numbersTapped(1)から
// 9ボタンが押された時numbersTapped(9)を設定していってみます。

        // 0ボタンが押された時
        binding.buttonZero.setOnClickListener {
            numbersTapped(0)
        }
        // 1ボタンが押された時
        binding.buttonZero.setOnClickListener {
            numbersTapped(1)
        }
        // 以下省略

なんと変更前152行あったものが148行になりました。全然減ってないけど引数の使い方が分かったのでよしとします。

今回のまとめ

引数がある関数を作った。
全文は以下。

package com.example.calculatorapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.calculatorapplication.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
        // 値を格納する変数
        var valueForTempStorage = 0.0 // 一時保存用の値
        var valueForCalc1st = 0.0 // 計算用の値1番目
        var valueForCalc2nd = 0.0 // 計算用の値2番目
        var valueForResults = 0.0 // 結果用の値
        // 記号を格納する変数
        var symbolForTempStorage = "" // 一時保存用の記号
        // 小数チェック用の変数
        var stringForPointZeroCheck = "" // .0チェック用の文字列
        var flagForDecimal = false // 小数チェック用のフラグ
        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(nambers : Int) {
            valueForTempStorage = valueForTempStorage * 10 + nambers
            binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
        }
        // 関数(fun)演算子(operator)タップした(Tapped)
        fun operatorTapped() {
            if (valueForCalc1st == 0.0) {
                valueForCalc1st = valueForTempStorage
                valueForTempStorage = 0.0
            }
            else if (valueForCalc2nd == 0.0) {
                valueForCalc2nd = valueForTempStorage
                valueForTempStorage = 0.0
                if (symbolForTempStorage == "+") {
                    valueForResults = valueForCalc1st + valueForCalc2nd
                }
                else if (symbolForTempStorage == "-") {
                    valueForResults = valueForCalc1st - valueForCalc2nd
                }
                else if (symbolForTempStorage == "*") {
                    valueForResults = valueForCalc1st * valueForCalc2nd
                }
                else if (symbolForTempStorage == "/") {
                    valueForResults = valueForCalc1st / valueForCalc2nd
                }
                stringForPointZeroCheck = valueForResults.toString()
                stringForPointZeroCheck = stringForPointZeroCheck.indexOf(".0").toString()
                if (stringForPointZeroCheck == "-1") {
                    flagForDecimal = true
                }
                if (flagForDecimal) {
                    binding.textViewValuedisplay.text = valueForResults.toString()
                }
                else {
                    binding.textViewValuedisplay.text = valueForResults.toInt().toString()
                }
                valueForCalc1st = valueForResults
                valueForCalc2nd = 0.0
                valueForResults = 0.0
                flagForDecimal = false
            }
        }
        // 0ボタンが押された時
        binding.buttonZero.setOnClickListener {
            numbersTapped(0)
        }
        // 1ボタンが押された時
        binding.buttonOne.setOnClickListener {
            numbersTapped(1)
        }
        // 2ボタンが押された時
        binding.buttonTwo.setOnClickListener {
            numbersTapped(2)
        }
        // 3ボタンが押された時
        binding.buttonThree.setOnClickListener {
            numbersTapped(3)
        }
        // 4ボタンが押された時
        binding.buttonFour.setOnClickListener {
            numbersTapped(4)
        }
        // 5ボタンが押された時
        binding.buttonFive.setOnClickListener {
            numbersTapped(5)
        }
        // 6ボタンが押された時
        binding.buttonSix.setOnClickListener {
            numbersTapped(6)
        }
        // 7ボタンが押された時
        binding.buttonSeven.setOnClickListener {
            numbersTapped(7)
        }
        // 8ボタンが押された時
        binding.buttonEight.setOnClickListener {
            numbersTapped(8)
        }
        // 9ボタンが押された時
        binding.buttonNine.setOnClickListener {
            numbersTapped(9)
        }
        // +ボタンが押されたとき
        binding.buttonAddition.setOnClickListener {
            operatorTapped ()
            symbolForTempStorage = "+"
        }
        // -ボタンが押されたとき
        binding.buttonSubtraction.setOnClickListener {
            operatorTapped ()
            symbolForTempStorage = "-"
        }
        // ×ボタンが押されたとき
        binding.buttonMultiplication.setOnClickListener {
            operatorTapped ()
            symbolForTempStorage = "*"
        }
        // ÷ボタンが押されたとき
        binding.buttonDivision.setOnClickListener {
            operatorTapped ()
            symbolForTempStorage = "/"
        }
        // =ボタンが押されたとき
        binding.buttonEqual.setOnClickListener {
            operatorTapped ()
            symbolForTempStorage = ""
        }
        // ACボタンが押されたとき
        binding.buttonAllClear.setOnClickListener {
            valueForTempStorage = 0.0
            valueForCalc1st = 0.0
            valueForCalc2nd = 0.0
            valueForResults = 0.0
            flagForDecimal = false
            symbolForTempStorage = ""
            binding.textViewValuedisplay.text = ""
        }
    }
}

コメント