初めてのAndroidアプリに割勘計算アプリを作ると決め、AndroidStudioをインストールして環境構築をして前回までで画面の作成まで終わりました。
前回:【Androidアプリ開発 vol.07】割勘計算アプリ② 画面の作成!部品の配置と文字列リソースの定義
ここからはいよいよプログラミングです。開発言語であるKotlinで[MainActvity.kt]ファイルにプログラムを書いていきます。アプリの完成まであと1歩!
目次
MainActivity.kt ファイル
[MainActivity.kt]は新規プロジェクト作成時にデフォルトで表示されていたファイルです。以下のスクリーンショットの赤枠2つのうちのどちらかをクリックして、[MainActivity.kt]を画面に表示させます。
完成したMainActivity.kt
とりあえずビルドして正常に動作することを確認したソースコードを載せておきます。
僕の作った初のAndroidアプリ、割勘計算アプリのソースコードです。
package kuneoresearch.com.waricalc import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.EditText import android.widget.TextView class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val button = findViewById<Button>(R.id.b_keisann) button.setOnClickListener { //未入力判定用のフラグ var isValid = true //合計金額入力欄の値を取得 val get_goukei = findViewById<EditText>(R.id.et_goukei) val st_goukei = get_goukei.text.toString() //合計金額入力欄が空欄になっていないかをチェック if(st_goukei.isEmpty()) { get_goukei.error = getString(R.string.et_goukei_error) isValid = false } //人数入力欄の値を取得 val get_ninnzuu = findViewById<EditText>(R.id.et_ninnzuu) val st_ninnzuu = get_ninnzuu.text.toString() //人数入力欄が空欄になっていないかをチェック if(st_ninnzuu.isEmpty()) { //人数が未入力の場合 get_ninnzuu.error = getString(R.string.et_ninnzuu_error) isValid = false } //合計金額入力欄、人数入力欄に値が入っている場合 if(isValid) { //合計金額入力欄、人数入力欄の値を文字列型から整数型に変換 val goukei = Integer.parseInt(st_goukei) val ninnzuu = Integer.parseInt(st_ninnzuu) //計算 val kekka = goukei / ninnzuu //1人分の金額表示欄を取得して、計算結果を表示 val set_kekka = findViewById<TextView>(R.id.tv_kekka_disp) set_kekka.text = getString(R.string.set_kekka, kekka) } } } }
ちなみに前回までの手順にそってIDを揃えて作っていたとしても、これをそのままコピペしてもエラーが出てしまいます。(MainActivity.ktで記述していく上で文字列リソースを定義してIDに変換される箇所がある為、後述します)
プログラミングしていく上でコピペは多用することになるかと思いますが、以降に1つ1つ解説していきますので、仕組みを理解して書き換えるところは書き換えて使ってくださいな。
デフォルトのソース
それじゃ作成したソースを上から順番に説明していきます。
まず新規プロジェクト作成時の状態で表示されているこのソース
package kuneoresearch.com.waricalc import android.support.v7.app.AppCompatActivity import android.os.Bundle class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
1行目のpackage ~で新規プロジェクト作成時に入力した[Company Domain].[Application name]が表示されていますね。
その次にimport ~ で始まる部分。ここではMainActivity.ktで宣言していないクラスやメソッドを使う為に、すでに宣言されているパッケージを読み込んでます。importすることで宣言なしでそれらのクラスやメソッドを使えるようになります。これは後でTextViewやButtonを指定するときに関わってきます。
そしてその次に Class MainActivityが宣言されています。
その中のoverrideで始まる3行は、Androidアプリ起動時に最初に呼び出される部分で画面の生成がなされます。
割勘計算アプリを作る上で、これらのデフォルトで生成されているソースはそのまま使います。なので、setContentViewメソッドの直後からプログラムを書いていきます。
計算ボタンの実装
この割勘計算アプリは超簡単アプリなので、計算ボタンが押された後の処理だけ書けば完成します。
OnCreateが呼ばれた後に計算ボタンが押された時の処理を書いたのが以下の部分です。
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val button = findViewById<Button>(R.id.b_keisann) button.setOnClickListener { //ここに計算ボタンがタップされた時の処理を書く } }
まず、以下の1文で前回作成したactivity_main.xmlから計算ボタンを参照しています。
val button = findViewById<Button>(R.id.b_keisann)
findViewById()はIDを指定することでactivity_main.xmlに設置したTextViewやButtonへの参照を取得するメソッドです。activity_main.xmlのButton部品類のIDが[b_keisann]というボタンを参照を取得してbuttonという変数に代入しています。
簡単に言うと、これから計算ボタン使うよー!って宣言するために書いています。
そして次に計算ボタンへの参照を取得して代入したbutton変数を使って、計算ボタンがタップされたらこう動いてね!というメソッドを書きます。
button.setOnClickListener {
//ここに計算ボタンがタップされた時の処理を書く
}
コメントアウトに書いている通り、このbutton.setOnClickListener{}メソッドの中に計算ボタンがタップされた時の処理を書いていきます。set.OnClickListenerの頭に付いているbuttonはさきほど計算ボタンへぼ参照を取得したbutton変数さんです。
さて。ここまで書くと以下のスクリーンショットのように、計算ボタンへの参照を所得した箇所の<Button>が赤く表示されてエラーが発生するかと思います。これは「Buttonってなによ?参照できねーよ!」ってAndroidStudioに言われています。
<Button>マウスオーバーするとAndroidStudioさんは親切にも「もしかしてactivity_main.xmlのButton使いたいの?」って聞いてくれています。
一番右横にこのショートカットが表示されていますね。[option]+[Enter]キーを押します(Macの場合)。
そうすると、MainActivity.ktの頭の方で<Button>を参照するためのImport文が追加されます。
これで<Button>の赤字表示が消え、Buttonを参照できるようになりました。この先TextViewの参照を取得する時にIDを指定しますが、赤字表示されたら同じように[option]+[Enter]キーを押して、Import文を追加してくだされ。
合計金額、人数の数値の取得と未入力エラー時の対応
さ、次!次!
button.set.OnClickListenerメソッド内を書いていきます。
button.setOnClickListener { //未入力判定用のフラグ var isValid = true //合計金額入力欄の値を取得 val get_goukei = findViewById<EditText>(R.id.et_goukei) val st_goukei = get_goukei.text.toString() //合計金額入力欄が空欄になっていないかをチェック if(st_goukei.isEmpty()) { get_goukei.error = getString(R.string.et_goukei_error) isValid = false } //人数入力欄の値を取得 val get_ninnzuu = findViewById<EditText>(R.id.et_ninnzuu) val st_ninnzuu = get_ninnzuu.text.toString() //人数入力欄が空欄になっていないかをチェック if(st_ninnzuu.isEmpty()) { //人数が未入力の場合 get_ninnzuu.error = getString(R.string.et_ninnzuu_error) isValid = false }
まず最初にisValid変数を宣言してTrueを代入しています。
このisValid変数は合計金額と人数が入力されているかを判定するためのフラグです。たった2つしか入力欄がないのに、入力を忘れてしまうユーザーがこの広い世界の中にはいます。
入力欄を空欄のまま処理を実行して、こちらの意図しない動作が起きないようにあらかじめ空欄だった場合は処理をしないようにはじいてあげます。
こんな風にね。
入力欄が空欄かを判定するフラグ isValid変数を宣言してTrueを代入したら、合計金額欄に入力された値を取得して、値が入力されているか空欄になっているかを判定する処理を入れます。
基本的にコメントアウトを読んでもらえばわかると思いますが、入力された合計金額の取得はさきほどボタンを取得したときと同じようにfindViewById()メソッドで合計金額入力のEditTextのIDを指定して参照を取得しています。
そしてその後にst_goukei変数を宣言して合計金額欄に入力された値をString型(文字列型)で代入しています。この時点でst_goukeiに入っている値はString型だということに注意が必要です。このままでは計算ができないので、後でInt型(整数型)に変換します。
st_goukei変数に値を代入したら、次はこのst_goukei変数を使って値が入っているどうかの判定を行います。それが次の1文です。
//合計金額入力欄が空欄になっていないかをチェック
if(st_goukei.isEmpty()) {
get_goukei.error = getString(R.string.et_goukei_error)
isValid = false
}
if(st_goukei.isEmpty())は、「もしも st_goukei に値が入っていなかったら以降に書かれた処理を実行する」という条件文です。st_goukeiに値が入っていなかった時にそれ以降に書かれた処理を実行して、値が入っていれば無視されます。
以下の一文で値が空欄だった時にエラー用のテキストを表示するようにしています。
get_goukei.error = getString(R.string.et_goukei_error)
さきほど合計金額の参照を取得する時に代入した get_goukei変数のお尻に .error を付けてget_goukei.errorで合計金額入力欄にエラーを表示するようにしています。そしてgetString()メソッドのカッコ内に表示するテキストを記述しています。
R.string.et_goukei_errorとなっていますが、これは変換後の記述でもともとは以下のスクリーンショットのように書いていました。
"合計金額を入力してね" と。
前回の画面作成時に書いた通り、このエラー時のメッセージのテキストも文字列リソースに定義する必要があるので、右側の電球アイコンをクリックして[Extra string resource]を選択して、[Resource name]を入力します。
こんな風にね。
これで、合計金額欄が空欄だった場合に、"合計金額を入力してね"と表示されるようになります。
最後にisValid変数にfalseを代入して、合計金額と人数が空欄かどうかをチェックするフラグにfalseを持たせておきます。
これで合計金額入力欄の値の取得と空欄判定処理を書き終えました。同じ要領で人数入力欄の値の取得と空欄判定処理を書いてしまいます。(人数入力欄の部分はやっていることが合計金額入力欄とまったく同じなので割愛します)
合計金額、人数が入力されている時の計算処理と表示
合計金額入力欄、人数入力欄の値の取得と空欄時のエラー表示処理を書き終えたら次は最後の処理です。
ここで合計金額入力欄、人数欄に値が入っていた時に割勘の計算をする処理を書いています。
//人数入力欄が空欄になっていないかをチェック if(st_ninnzuu.isEmpty()) { //人数が未入力の場合 get_ninnzuu.error = getString(R.string.et_ninnzuu_error) isValid = false } //合計金額入力欄、人数入力欄に値が入っている場合 if(isValid) { //合計金額入力欄、人数入力欄の値を文字列型から整数型に変換 val goukei = Integer.parseInt(st_goukei) val ninnzuu = Integer.parseInt(st_ninnzuu) //計算 val kekka = goukei / ninnzuu //1人分の金額表示欄を取得して、計算結果を表示 val set_kekka = findViewById<TextView>(R.id.tv_kekka_disp) set_kekka.text = getString(R.string.set_kekka, kekka) }
if(isValid)は、isValid変数がTrueだったら以降の処理を実行してねという条件文です。
一番始めにisValid変数を宣言した時にtrueを代入しましたが、合計金額入力欄、人数入力欄の値を取得時に空欄かどうかのチェックを受けてきて空欄だった場合はfalseを代入する処理を上で入れましたね。
つまり空欄判定をすべてパスしてきたらtrueのままになっているはずです。
その時はじめてここで書く処理、割勘の計算が行われます。
//合計金額入力欄、人数入力欄の値を文字列型から整数型に変換
val goukei = Integer.parseInt(st_goukei)
val ninnzuu = Integer.parseInt(st_ninnzuu)
if文直後のこの部分では、取得して代入した st_gouke と st_ninnzuu をString型(文字列型)からInt型(整数型)に変換しています。(さきほどString型では計算できないと書きましたね)。String型からInt型へと変換されたgoukei変数とninnzuu変数を使って計算します。
それが次の1文です。
//計算
val kekka = goukei / ninnzuu
割勘なので合計金額を人数で割って、kekka変数に代入しています。
で、最後にkekka変数に入れられた計算結果を画面に表示させるために以下の処理を書きます。
//1人分の金額表示欄を取得して、計算結果を表示
val set_kekka = findViewById<TextView>(R.id.tv_kekka_disp)
set_kekka.text = getString(R.string.set_kekka, kekka)
計算結果表示用のTextViewの参照を取得後、計算結果表示用のTextViewに表示する計算結果を表示するように書いています。
getString()メソッドの中の(R.string.set_kekka, kekka)ですが、kekka変数はさきほど計算した結果の値が代入されています。R.string.set_kekkaはTextViewに表示されるメッセージが入っています。
さきほど合計金額入力欄が空欄だった時のエラーメッセージを文字列リソースに定義しましたが、今度は計算結果のメッセージを先に[Resource name]から書いた逆パターンです。
いきなり[Resource name]を書いたら、当たり前ですが、赤字のエラーとなります。なので電球アイコンから[Create string value resource 'set_kekka']を選択して文字列リソースの定義をします。
今度は[Resource Name]がすでに入力されているので[Resource value]に計算結果のTextViewに表示させるテキストを入力します。以下では "%1$,3d円だよ" と入力しています。ここの赤字の%1$,3dにkekka変数の値が入ります。
割引計算アプリが完成!
さあ、これでプログラムは書き終わりました。
後はエミュレータか実機で実行して、ちゃんと動くか確認します。
これにて3回にわけて書いてきた割引計算アプリが完成しました。
初めてAndroidアプリを作ってみましたが、この割引計算アプリはまだまだ改良すべき部分がたくさんあります。次はこのアプリを改良していきたいと思います。
(つづく)