アプリを作ってみる 電卓編【Androidアプリ開発】

実際にアプリを作成してみます。

今回は足し算・引き算を行う電卓を簡単に作っていきます。
ちゃんとした電卓を作るのは結構大変なので、ざっくりと作っていきます。

実装

レイアウト

画面を作っていきます。

テーブルの作り方についてはこちらで解説しています。

用意するコンポーネント

  • TextView×2
    計算過程表示、入力値・計算結果表示
  • ボタン×14
    0~9、CLEAR、+、-、=

デザイン機能で以下のように配置していきます。

テーブルレイアウト
<TableLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <TextView
            android:id="@+id/textTemp"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_span="4" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="2">

        <TextView
            android:id="@+id/textResult"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_span="4" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <Button
            android:id="@+id/button7"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="7" />

        <Button
            android:id="@+id/button8"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="8" />

        <Button
            android:id="@+id/button9"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="9" />

        <Button
            android:id="@+id/buttonClear"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="Clear" />

    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <Button
            android:id="@+id/button4"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="4" />

        <Button
            android:id="@+id/button5"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="5" />

        <Button
            android:id="@+id/button6"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="6" />

        <Button
            android:id="@+id/buttonSub"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="-" />

    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="2" />

        <Button
            android:id="@+id/button3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="3" />

        <Button
            android:id="@+id/buttonAdd"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="+" />

    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <Button
            android:id="@+id/button0"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="0" />

        <Button
            android:id="@+id/buttonResult"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="=" />

    </TableRow>
</TableLayout>

アクティビティ

ロジック

今回は、足し算・引き算のみなので、優先順位を気にせず前方から順に計算していきます。

  1. 計算式の入力
    数字、演算子をリストに格納していく。
    →演算子入力時にリストに格納する。
  2. 演算
    以下の計算を演算子の数分繰り返し行う。
    ①x = 数字[0] + 数字[1] or 数字[0] – 数字[1]
    ②数字[0] = x
    ③数字[1]を削除

「1+2+3+4+5」と入力して計算した場合、以下のような流れになります。

計算回数計算結果リストの値
初期値1,2,3,4,5
1回目1+2=33,3,4,5
2回目3+3=66,4,5
3回目6+4=1010,5
4回目10+515
(計算結果)

ソースコード

MainActivityファイルに処理を書いていきます。

大きく分けると以下の処理が必要となります。

  • アクティビティ開始時の処理
    初期処理、イベントリスナの設定
  • 数字ボタンを押したときの処理
    画面への入力
  • 数字以外のボタンを押したときの処理
    計算式の作成、計算結果の表示

今回作成したソースでは、Int型の最大値を超える計算を行うと正しい計算が出来ません。

class MainActivity : AppCompatActivity() {
    companion object {
        lateinit var textResult: TextView
        lateinit var textTemp: TextView
        var clickedNum = mutableListOf<Int>()
        var clickedOpe = mutableListOf<Int>()
        const val MAX_LENGTH = 9
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //TextViewコンポーネントの取得
        textResult = findViewById(R.id.textResult)
        textTemp = findViewById(R.id.textTemp)

        //クリックイベントのインスタンス化
        val numberButtonClick = NumberButtonClick()
        val opeButtonClick = OpeButtonClick()

        //ボタンコンポーネントの取得
        val button0: Button = findViewById(R.id.button0)
        val button1: Button = findViewById(R.id.button1)
        val button2: Button = findViewById(R.id.button2)
        val button3: Button = findViewById(R.id.button3)
        val button4: Button = findViewById(R.id.button4)
        val button5: Button = findViewById(R.id.button5)
        val button6: Button = findViewById(R.id.button6)
        val button7: Button = findViewById(R.id.button7)
        val button8: Button = findViewById(R.id.button8)
        val button9: Button = findViewById(R.id.button9)
        val buttonClear: Button = findViewById(R.id.buttonClear)
        val buttonAdd: Button = findViewById(R.id.buttonAdd)
        val buttonSub: Button = findViewById(R.id.buttonSub)
        val buttonResult: Button = findViewById(R.id.buttonResult)

        //各ボタンにクリックリスナを設定
        button0.setOnClickListener(numberButtonClick)
        button1.setOnClickListener(numberButtonClick)
        button2.setOnClickListener(numberButtonClick)
        button3.setOnClickListener(numberButtonClick)
        button4.setOnClickListener(numberButtonClick)
        button5.setOnClickListener(numberButtonClick)
        button6.setOnClickListener(numberButtonClick)
        button7.setOnClickListener(numberButtonClick)
        button8.setOnClickListener(numberButtonClick)
        button9.setOnClickListener(numberButtonClick)
        buttonClear.setOnClickListener(opeButtonClick)
        buttonAdd.setOnClickListener(opeButtonClick)
        buttonSub.setOnClickListener(opeButtonClick)
        buttonResult.setOnClickListener(opeButtonClick)

    }

    class NumberButtonClick() : View.OnClickListener {
        override fun onClick(v: View?) {
            if (v != null) {
                //クリックされたボタンを取得
                val button: Button = v.findViewById(v.id)

                //最大文字数を越えていない場合のみ入力を受け付ける
                if(textResult.text.length < MAX_LENGTH) {
                    if (Integer.parseInt(button.text.toString()) <= 9) {
                        if (textResult.text.isEmpty()) {
                            textResult.text = button.text
                        } else {
                            if (textResult.text.equals("0")) {
                                //0始まりの場合は連続で入力させない
                                textResult.text = button.text
                            } else {
                                //それ以外は入力値を末尾に追加する
                                var tempStr = textResult.text.toString() + button.text
                                textResult.text = tempStr
                            }
                        }
                    }
                }
            }
        }
    }

    class OpeButtonClick() : View.OnClickListener {
        override fun onClick(v: View?) {
            if (v != null) {
                if(textResult.text.isNotEmpty()) {
                    //クリックされたボタンを取得
                    val button: Button = v.findViewById(v.id)

                    when (v.id) {
                        R.id.buttonAdd -> {
                            addTempText(button)
                        }
                        R.id.buttonSub -> {
                            addTempText(button)
                        }
                        R.id.buttonClear -> {
                            allClear()
                        }
                        R.id.buttonResult -> {
                            calcResult()
                        }
                        else -> {
                        }
                    }
                }
            }
        }

        private fun addTempText(button: Button) {
            clickedNum.add(Integer.parseInt(textResult.text.toString()))
            clickedOpe.add(button.id)

            var tempStr = textTemp.text.toString() +
                    textResult.text.toString() +
                    button.text.toString()
            textTemp.text = tempStr
            textResult.text = ""
        }

        private fun allClear() {
            textTemp.text = ""
            textResult.text = ""
            clickedNum.clear()
            clickedOpe.clear()
        }

        private fun calcResult() {
            clickedNum.add(Integer.parseInt(textResult.text.toString()))

            //入力値を前方から順に計算する
            clickedOpe.forEach { buttonId ->
                if(clickedNum.size > 1) {
                    val number1 = clickedNum[0]
                    val number2 = clickedNum[1]

                    when (buttonId) {
                        //計算結果を格納し直す
                        R.id.buttonAdd -> {
                            clickedNum[0] = number1 + number2
                        }
                        R.id.buttonSub -> {
                            clickedNum[0] = number1 - number2
                        }
                    }
                }

                //計算が終わった値を削除する
                clickedNum.removeAt(1)
            }

            //入力を初期化して計算結果を表示する
            textResult.text = clickedNum[0].toString()
            textTemp.text = ""
            clickedNum.clear()
            clickedOpe.clear()
        }
    }
}

まとめ

足し算・引き算のみを行う簡易な電卓を作成しました。
まずは、Android Studioや言語に慣れるために、書いてみると手っ取り早く覚えられます。
しっかり身につくまでは、こだわり過ぎず実践していくと良いでしょう。

実機にインストールする方法も紹介しています。

Androidアプリ開発
この記事を書いた人

エンジニアとして仕事をしています。
仕事や趣味を通して、開発やプログラミングについて学んだことを綴っていきます。
 ・実務経験は、WEBシステムのサーバーサイドコーディングがメイン
 ・アプリ開発は趣味程度

akihiro-takedaをフォローする
akihiro-takedaをフォローする
プログラミング・開発の備忘録
タイトルとURLをコピーしました