【初心者がAndroid Studio+kotlinで電卓アプリを作ってみる】第11回:小数点ボタンと処理の追加編

kotlinで電卓アプリ作成

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

今回のポイント

.ボタンとその処理を追加してみたいと思っています。

.ボタンの追加

例のごとくactivity_main.xmlにボタンを追加します。
idはbuttonPointにしてみました。

そしてtextViewValuedisplayのサイズも変更してみました。
Layout_heightを80dpから90dpに変えました。ちょっとだけ数字の下が切れているのが気になっていたので。

処理の追加

ここから迷走が始まりますのでマネしないように。

メモみたいなものなので読み飛ばしてもいいです。

迷走その1

MainActivity.ktに移動して処理を書いていきます。
何となく書く場所はここら辺にしとこう。

        // .ボタンが押されたとき
        binding.buttonPoint.setOnClickListener {
            
        }

うーん、”.”て難しいですね。数字ではないけど数字として扱わないといけないというか…
なのでひとまず関数に入れないで書いていきたいと思います。まずは表示するようにしました。

        // .ボタンが押されたとき
        binding.buttonPoint.setOnClickListener {
            binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString() + "."
        }

実行してみたところ。
0.1と押すと1になってしまいます。
1.2と押すと12になってしまいます。
numbersTapped関数は数字が押されたら10倍しているだけなのでそうなってしまいます。

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

では”.”が表示画面に無かった場合今まで通り10倍してnambersを足す
valueForTempStorage * 10 + nambers
その他は10倍にしない。
っていうif文を追加してみる。(間違い)

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(nambers : Int) {
            // "."が表示画面に無かった場合
            if (binding.textViewValuedisplay.text.indexOf(".") == -1) {
                valueForTempStorage = valueForTempStorage * 10 + nambers
            }
            // "."が表示画面にあった場合
            else {
                valueForTempStorage = valueForTempStorage + nambers
            }
            binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
        }

1.2を押したら3が表示されます。
これ足し算しているだけだ。
閃いた1/10したらよいのではと。(間違い)

valueForTempStorage = valueForTempStorage / 10 + nambers

1.0/10+2をスマホの電卓で確認したら確かに2.1でした。
1と2が手持ちの状態で1.2を答えにするのはどんな計算か計算苦手な私が考えてみた、
というかスマホの電卓で色々と計算してみた結果
1+2÷10=1.2
出来た!義務教育レベルの計算が出来なくて悲しくなりましたが変えてみます。(間違い)

valueForTempStorage = valueForTempStorage + nambers / 10

実行してみましたがまだダメです。
今度は1.2を押したら1が表示されました。
この現象はその7でみた、多分textViewValuedisplayに表示する際Int表示だから.2が省略されて表示されているのではないかと思い変更します。

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(nambers : Int) {
            // "."が表示画面に無かった場合
            if (binding.textViewValuedisplay.text.indexOf(".") == -1) {
                valueForTempStorage = valueForTempStorage * 10 + nambers
                binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
            }
            // "."が表示画面にあった場合
            else {
                valueForTempStorage = valueForTempStorage + nambers / 10
                binding.textViewValuedisplay.text = valueForTempStorage.toString()
            }
            // binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
        }

1.2をおしたら1.0か…まだだめなの…考えます。
あ、これだ!
Intの2÷10は2になって
Doubleの2.0÷10は0.2なるのか。

// fun numbersTapped(nambers : Int) {
   fun numbersTapped(nambers : Double) {

Double型に変えるとエラーが出ますので.0を追加していきます変更します。

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

これでどうだ!
実行結果
1.2押下時1.2が表示されました。
1.0押下時1.0が表示されました。
0.1押下時0.1が表示されました。
やりました!勝った気がします!(本当は負け)

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(nambers : Int) {
            // "."が表示画面に無かった場合
            if (binding.textViewValuedisplay.text.indexOf(".") == -1) {
                valueForTempStorage = valueForTempStorage * 10 + nambers
                binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
            }
            // "."が表示画面にあった場合
            else {
                valueForTempStorage = valueForTempStorage + nambers / 10
                binding.textViewValuedisplay.text = valueForTempStorage.toString()
            }
        }

次に1.23を表示しようとしたら1.5が表示された…
次に1.2の後3が押された場合はnambers / 10をnambers / 100にして…
1.2足す0.03になるから1.23…
では0が押された場合は多分1.2のままですので1.02とかの表示が出来ない…
もうだめだ、もう計算ではわからないから強引にString型でやってみることにします。(算数苦手)

迷走その2

もうわからんのでいちどその10のコードに戻しました。
“.”が押された時、単純に表示画面(binding.textViewValuedisplay.text)に”.”を繋げてみます。
これで”.”が表示されるようになりました。

        // .ボタンが押されたとき
        binding.buttonPoint.setOnClickListener {
            binding.textViewValuedisplay.text = binding.textViewValuedisplay.text.toString() + "."
        }

このままだといきなり”.”が表示されてしまいます。
さらに”.”ボタンを連打出来てしまうのでそれを回避していきたいと思います。

        // .ボタンが押されたとき
        binding.buttonPoint.setOnClickListener {
            // いきなり.ボタンを押しても.を表示しない&&(かつ)連打させない
            if (binding.textViewValuedisplay.text != "" && symbolForTempStorage != ".") {
                binding.textViewValuedisplay.text = binding.textViewValuedisplay.text.toString() + "."
                symbolForTempStorage = "."
            }
        }

しかし1.2と押すと12になってしまいます。
てことはnumbersTapped関数を修正しないといけないです。
これを

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

こうしてみました。

        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(nambers : Int) {
            // "."が表示画面に無かった場合は今まで通り
            if (binding.textViewValuedisplay.text.indexOf(".") == -1) {
                valueForTempStorage = valueForTempStorage * 10 + nambers
                binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
            }
            // "."が表示画面に有った場合
            else {
                // 結果画面の文字と押された数字を結合して結果画面に表示する
                binding.textViewValuedisplay.text = binding.textViewValuedisplay.text.toString() + nambers.toString()
                // 一時保存用の値にダブル型で結果を入れておく
                valueForTempStorage = binding.textViewValuedisplay.text.toString().toDouble()
            }
        }

1.2+を押すと表示が0になる。
その10の=の後+ボタンを押した状態とと同じなのでこれで解決

                else if (symbolForTempStorage == ".") {
                    return
                }

つぎは1.2+3を押すと表示が1.23になる。

1.2+3=3問題
valueForCalc1stがずっと0なのが問題なので
symbolForTempStorageが”.”の場合もvalueForCalc1stに数値を入れる

        // 関数(fun)演算子(operator)タップした(Tapped)
        fun operatorTapped() {
            if (valueForCalc1st == 0.0 && symbolForTempStorage == "" || symbolForTempStorage == ".") {
                valueForCalc1st = valueForTempStorage
                valueForTempStorage = 0.0
            }

1.2+3=4.2出来ました!
3+1.2=1.2…もういやだ。
symbolForTempStorageに”.”を入れないほうがいいかも?
これもう”.”は演算子じゃなくて数字として扱ったほうがいいのかも?

フラグを作って解決

フラグでようやく解決に至りました。最難関でした。

var flagForDecimal2 = false // 小数チェック用のフラグ2を用意して、

if (flagForDecimal2 == true) {
// 結果画面の文字と押された数字を結合して結果画面に表示する

単純に文字列を結合することにして解決。

下に変更前変更後のコードを置いておきました。

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 && symbolForTempStorage == "") {
                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
                }
                else if (symbolForTempStorage == "=") {
                    return
                }
                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 = ""
        }
    }
}

変更前

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 // 小数チェック用のフラグ
        var flagForDecimal2 = false // 小数チェック用のフラグ2
        // 関数(fun)数字(numbers)タップした(Tapped)
        fun numbersTapped(namString: String) {
            if (flagForDecimal2 == true) {
                // 結果画面の文字と押された数字を結合して結果画面に表示する
                binding.textViewValuedisplay.text = binding.textViewValuedisplay.text.toString() + namString
                // 一時保存用の値にダブル型で結果を入れておく
                valueForTempStorage = binding.textViewValuedisplay.text.toString().toDouble()
            }
            else {
                valueForTempStorage = valueForTempStorage * 10 + namString.toInt()
                binding.textViewValuedisplay.text = valueForTempStorage.toInt().toString()
            }
        }
        // 関数(fun)演算子(operator)タップした(Tapped)
        fun operatorTapped() {
            if (valueForCalc1st == 0.0 && symbolForTempStorage == "") {
                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
                }
                else if (symbolForTempStorage == "=") {
                    return
                }
                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
            }
            flagForDecimal2 = 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.buttonPoint.setOnClickListener {
            // いきなり"."が押された場合は無視する、"."連打も無視する
            if (binding.textViewValuedisplay.text != "" && flagForDecimal2 != true) {
                flagForDecimal2 = true
                numbersTapped(".")
            }
        }
        // +ボタンが押されたとき
        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
            flagForDecimal2 = false
            symbolForTempStorage = ""
            binding.textViewValuedisplay.text = ""
        }
    }
}

変更後

コメント