LoginSignup
11
15

More than 5 years have passed since last update.

アプリ開発初心者がAndroid電卓アプリをつくってみた

Last updated at Posted at 2019-01-06

はじめに

以下のサイトを参考にJavaでAndroid電卓アプリを作ってみました。
以下のサイトではKotlinを使っていましたが、初めてのAndroidアプリ作成なのでこの記事はJavaで書いたプログラムです。
Android Studioで電卓アプリを作る

工夫した点

計算誤差を防ぐためにdouble型ではなくBigdecimal型を使用

最初は計算処理をdouble型を用いて行っていましたが、以下のサイトの通り計算誤差が出てしまいましたので、それを防ぐためにBigdecimal型を使いました。
数値Double型の誤差が発生する原因について ~ 2進数の小数って面倒いねって話 ~

参考サイト

プログラム

デザイン

ソースコード

styles.xml
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

styleのparent属性をNoActionBarに変更。電卓アプリにアクションバーは不要であるため。

color.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- DefaultColorChoice -->
    <!--<color name="colorPrimary">#008577</color>-->
    <!--<color name="colorPrimaryDark">#00574B</color>-->
    <!--<color name="colorAccent">#D81B60</color>-->
    <color name="colorPrimary">#2196F3</color>
    <color name="colorPrimaryDark">#1976D2</color>
    <color name="colorAccent">#EF5350</color>
</resources>

自分好みの色にデザインを変更。以下のサイトが色の組み合わせの参考になる。
マテリアルデザインカラー色の組み合わせ見本集

strings.xml
<resources>
    <string name="app_name">Calculator</string>
    <string name="formula_text" />
</resources>
activity_calc.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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=".CalcActivity">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.4" />

    <TableLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline">

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

            <TextView
                android:id="@+id/tvFormula"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_span="4"
                android:layout_weight="1"
                android:paddingEnd="8dp"
                android:gravity="end"
                android:text="@string/formula_text"
                android:textSize="30sp" />
        </TableRow>

        <TableRow
            style="?android:attr/buttonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <Button
                android:id="@+id/btClear"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="C"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btDivide"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="÷"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btMultiply"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="×"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btDelete"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="DEL"
                android:textColor="@color/colorPrimaryDark" />
        </TableRow>

        <TableRow
            style="?android:attr/buttonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <Button
                android:id="@+id/btSeven"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="7"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btEight"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="8"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btNine"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="9"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btPercent"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="%"
                android:textColor="@color/colorPrimaryDark" />
        </TableRow>

        <TableRow
            style="?android:attr/buttonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <Button
                android:id="@+id/btFour"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="4"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btFive"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="5"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btSix"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="6"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btSubtract"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="-"
                android:textColor="@color/colorPrimaryDark" />
        </TableRow>

        <TableRow
            style="?android:attr/buttonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <Button
                android:id="@+id/btOne"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="1"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btTwo"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="2"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btThree"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="3"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btAdd"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#e9e9e9"
                android:text="+"
                android:textColor="@color/colorPrimaryDark" />
        </TableRow>

        <TableRow
            style="?android:attr/buttonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <Button
                android:id="@+id/btPlusMinus"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1" />
            <Button
                android:id="@+id/btZero"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="0"
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btPoint"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="."
                android:textColor="@color/colorPrimaryDark" />

            <Button
                android:id="@+id/btEqual"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="="
                android:textColor="#ffffff"
                android:background="@color/colorPrimaryDark"/>
        </TableRow>
    </TableLayout>

</android.support.constraint.ConstraintLayout>

widthとheightはハードコードしないように適宜工夫しています。

CalcActivity.java
package com.yagiyagi21.android.calculator;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import static android.webkit.ConsoleMessage.MessageLevel.LOG;

public class CalcActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calc);

        List<Button> buttonList = new ArrayList<>();
        // 数字ボタンを取得
        buttonList.add((Button) findViewById(R.id.btZero));
        buttonList.add((Button) findViewById(R.id.btOne));
        buttonList.add((Button) findViewById(R.id.btTwo));
        buttonList.add((Button) findViewById(R.id.btThree));
        buttonList.add((Button) findViewById(R.id.btFour));
        buttonList.add((Button) findViewById(R.id.btFive));
        buttonList.add((Button) findViewById(R.id.btSix));
        buttonList.add((Button) findViewById(R.id.btSeven));
        buttonList.add((Button) findViewById(R.id.btEight));
        buttonList.add((Button) findViewById(R.id.btNine));
        // 記号ボタンを取得
        buttonList.add((Button) findViewById(R.id.btAdd));
        buttonList.add((Button) findViewById(R.id.btSubtract));
        buttonList.add((Button) findViewById(R.id.btMultiply));
        buttonList.add((Button) findViewById(R.id.btDivide));
        buttonList.add((Button) findViewById(R.id.btEqual));
        // その他ボタンを取得
        buttonList.add((Button) findViewById(R.id.btClear));
        buttonList.add((Button) findViewById(R.id.btDelete));
        buttonList.add((Button) findViewById(R.id.btPoint));
        buttonList.add((Button) findViewById(R.id.btPlusMinus));
        buttonList.add((Button) findViewById(R.id.btPercent));

        ButtonListener listener = new ButtonListener();

        for(Button button : buttonList){
            button.setOnClickListener(listener);
        }
    }

    private class ButtonListener implements View.OnClickListener {

        private List<BigDecimal> _numList = new ArrayList<>();
        private List<Character> _opeList = new ArrayList<>();
        private String _inputValue = "";

        @Override
        public void onClick(View view) {
            TextView tvFormula = findViewById(R.id.tvFormula);

            // ボタン毎の処理を定義
            int btId = view.getId();
            char inputChar;
            switch (btId) {
                // 数字ボタンの場合
                case R.id.btZero:
                    inputChar = '0';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btOne:
                    inputChar = '1';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btTwo:
                    inputChar = '2';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btThree:
                    inputChar = '3';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btFour:
                    inputChar = '4';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btFive:
                    inputChar = '5';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btSix:
                    inputChar = '6';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btSeven:
                    inputChar = '7';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btEight:
                    inputChar = '8';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btNine:
                    inputChar = '9';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                // 記号ボタンの場合
                case R.id.btAdd:
                    inputChar = '+';
                    if(!(_inputValue.equals(""))) {
                        addList(tvFormula, _inputValue, inputChar);
                    }
                    break;
                case R.id.btSubtract:
                    inputChar = '-';
                    if(!(_inputValue.equals(""))) {
                        addList(tvFormula, _inputValue, inputChar);
                    }
                    break;
                case R.id.btMultiply:
                    inputChar = '×';
                    if(!(_inputValue.equals(""))) {
                        addList(tvFormula, _inputValue, inputChar);
                    }
                    break;
                case R.id.btDivide:
                    inputChar = '÷';
                    if(!(_inputValue.equals(""))) {
                        addList(tvFormula, _inputValue, inputChar);
                    }
                    break;
                case R.id.btEqual:
                    inputChar = '=';
                    if(!(_inputValue.equals(""))) {
                        addList(tvFormula, _inputValue, inputChar);
                    }
                    String result = calculate().toString();
                    tvFormula.setText(result);
                    _inputValue = result;

                    _numList.clear();
                    _opeList.clear();
                    break;
                // その他ボタンの場合の処理
                case R.id.btClear:
                    tvFormula.setText("");
                    _numList.clear();
                    _opeList.clear();
                    _inputValue= "";
                    break;
                case R.id.btDelete:
                    String formulaStr = tvFormula.getText().toString();
                    char formulaStrLastChar = formulaStr.charAt(formulaStr.length() - 1);

                    if (isFourArithmeticOpe(formulaStrLastChar)) {
                        _opeList.remove(_opeList.size() - 1);
                    }
                    if (!formulaStr.isEmpty()) {
                        tvFormula.setText(formulaStr.subSequence(0, formulaStr.length() - 1));
                    }
                    if (!_inputValue.isEmpty()) {
                        _inputValue = _inputValue.substring(0, _inputValue.length() - 1);
                    }
                    break;
                case R.id.btPoint:
                    inputChar = '.';
                    addTextView(tvFormula, inputChar);
                    _inputValue += inputChar;
                    break;
                case R.id.btPlusMinus:
                    break;
                case R.id.btPercent:
                    break;
            }
        }

        private void addList(TextView tvFormula, String inputValue, char ope) {
            addTextView(tvFormula, ope);
            _numList.add(new BigDecimal(inputValue));
            _opeList.add(ope);
            _inputValue = "";
        }

        private void addTextView(TextView textView, char addStr) {
            textView.setText(textView.getText().toString() + addStr);
        }

        private BigDecimal calculate() {
            int i = 0;

            while(i < _opeList.size()) {
                if(_opeList.get(i) == '×' | _opeList.get(i) == '÷') {
                    BigDecimal resultMultiDiv = _opeList.get(i) == '×' ? _numList.get(i).multiply(_numList.get(i+1)) : _numList.get(i).divide(_numList.get(i+1));

                    _numList.set(i, resultMultiDiv);
                    _numList.remove(i+1);
                    _opeList.remove(i);
                    i--;
                }
                else if(_opeList.get(i) == '-') {
                    _opeList.set(i, '+');
                    _numList.set(i+1, _numList.get(i+1).negate());
                }
                i++;
            }

            BigDecimal result = new BigDecimal("0");
            for(BigDecimal j : _numList) {
                result = result.add(j);
            }

            return result;
        }

        private boolean isFourArithmeticOpe(char c) {
            if(c == '+' | c == '-' | c == '*' | c == '/') return true;
            return false;
        }
    }
}
11
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
15