Androidプログラミングに挑戦2!(12)単位変換アプリを作る(その3)

0
    JUGEMテーマ:プログラミング

    今回も単位変換アプリをブラッシュアップしていきましょう。
    新しいテーマですが、今度はポンド→キログラムだけでなく、キログラム→ポンドも変換できるようにしてみたいと思います。要件を整理すると次の通りです。
    ・入力欄に入力した数値を単位変換して出力欄に表示する(従来通り)
    ・変換ボタンをタップしたときに変換操作を行う(従来通り)
    ・ドロップダウンメニューで変換方向を選択する(新機能)
    ・変換方向を選択すると同時に、入出力欄の右の単位表示も切り替える(新機能)
    ・入力欄が空の状態で変換ボタンをタップすると、出力欄に0が表示される(?)

    こう考えると、変換操作に関する部分は前回のまま使えそうです。新しくドロップダウンメニューを追加し、アイテムを選択すると同時に画面表示や変換係数を切り替える機能を追加すればよさそうです。
    なお、最後の項目は前回の積み残し、検証漏れです。今回併せて実装していきます。

    ではまず、レイアウトから。
    ドロップダウンメニューは、「スピナー」というウィジェットを使います。
    まず、LinerLayout(Horizontal)の中に、変換ボタンとこのスピナーを配置します。



    青い線で囲まれているのがスピナーです。
    レイアウトはこれだけです。なんと簡単!
    あともう一つ、ちょっと修正したい部分があります。入出力欄の長さが微妙に違うのが気になるのです。さらに変換ボタンをおして中に数値が表示されるとさらに大きさがずれ、単位の位置がぴょこっと動くのです。気になります。
    これは入出力欄の幅の設定が良くないために起こった現象です。
    レイアウトエディターで出力エリアのプロパティを見てみると、layout:widthがwrap_content、そしてlayout:weightに0.81という値が設定されていました。前者は「中身に合わせて幅を調整しなさい」という意味、後者はレイアウト枠内での他のコンポーネントとの幅の比率を指定するためのプロパティです。何となく2重指示になっていて、実際の優先順位がどうなっているかによって表示が予測できない、そして中の文字の長さが変わるとエリアの大きさも変わるので、隣に書かれている単位の文字がぴょこぴょこ動く、ということになっていたわけです。
    そこで、まずlayout:weightの値を消し、layout:widthに具体的な数字を設定してやることにします。
    レイアウトエディターでlayout:widthの欄をクリックし「…」をクリックします。
    表示されたダイアログで一番下の「New Resource」をクリックしたら表示される「New dimen Value」をクリック。
    更に表示されたダイアログで、Resource nameを「iowidth」、Resource valueを「180dp」と入力してOKをクリックします。



    同じことを入力欄についてもやってやります。今度は「New Resource」ではなく、表示されたリストの中に先ほど設定した「iowidth」があるはずなので、それを選択してやればOKです。
    これで入力と出力の欄の幅が等しく固定され、単位の表示がピコピコ動くことはなくなりました。


    続いてドロップダウンメニューの中身を定義していきましょう。
    これは、res¥values¥strings.xmlに直接書き込んでいきます。
    <resources>
        <string name="app_name">UnitConverter2</string>
        <string name="input">入力:</string>
        <string name="inputUnit">lb</string>
        <string name="output">出力:</string>
        <string name="initialOutput">0.0</string>
        <string name="outputUnit">kg</string>
        <string name="convert">変換</string>
        <string name="unit1">lb</string>
        <string-array name="menu">
            <item>lb → kg</item>
            <item>kg → lb</item>
        </string-array>
    </resources>
    

    9行目までは今までと一緒です。10〜13行目、「string-array」として定義されているのがドロップダウンメニューのアイテムになります。このstring-arrayをspinner側で呼び出してやります。具体的には、レイアウトエディターで「entries」のプロパティに「@array/menu」と打ち込んでください。



    上の図で、右の方の青い部分です。

    これが済んだらjavaを記入していきます。
    package com.example.tetsuya.unitconverter2;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    // 中で使用するEditText, TextView, Viewをimport
    import android.widget.EditText;
    import android.widget.TextView;
    import android.view.View;
    import android.widget.Spinner;
    import android.widget.AdapterView.OnItemSelectedListener;
    import android.widget.AdapterView;
    public class UnitConverter2 extends AppCompatActivity {
        // 使用する変数等を定義
        EditText editText;
        TextView textView4;
        TextView textView2;
        TextView textView5;
        double conversionRatio = 0.45359243; // lbs→kgの変換係数を初期値に
        double inputValue = 0;
        double outputValue = 0;
        String input;
        Spinner menuSpinner;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_unit_converter2);
            // 入力エリアと出力表示エリアのインスタンスを取得
            editText = (EditText) findViewById(R.id.editText);     // 入力エリア
            textView4 = (TextView) findViewById(R.id.textView4);    // 出力エリア
            textView2 = (TextView) findViewById(R.id.textView2);    // 入力側単位表示
            textView5 = (TextView) findViewById(R.id.textView5);    // 出力側単位表示
            menuSpinner = (Spinner) findViewById(R.id.spinner);     // メニュースピナー
            // 変換ボタンのオンクリックリスナーを設定
            findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) { // ボタンクリック時の処理を定義
                    // 入力欄に記入されたテキストを取得
                    input = editText.getText().toString();
                    // 取得したテキストを数値に変換
                    if (!input.equals("")){
                        inputValue = Double.parseDouble(input);
                    }else{
                        inputValue = 0;
                    }
                    // 入力単位→出力単位に変換
                    outputValue = inputValue * conversionRatio;
                    // 変換した数値を文字列として出力エリアにセット
                    textView4.setText(String.valueOf(outputValue));
                }
            });
            // spinnerのアイテムセレクトリスナーを設定
            // リスナーを登録
            menuSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
                // アイテムが選択された時
                public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) {
                    int idx = menuSpinner.getSelectedItemPosition();
                    switch(idx){
                        case 0:
                            conversionRatio = 0.45359243;
                            textView2.setText(R.string.inputUnit);
                            textView5.setText(R.string.outputUnit);
                            break;
                        case 1:
                            conversionRatio = 2.20462233;
                            textView2.setText(R.string.outputUnit);
                            textView5.setText(R.string.inputUnit);
                            break;
                    }
                }
                // アイテムが選択されなかった
                public void onNothingSelected(AdapterView<?> parent) {
                }
            });
        }
    }
    
    前回から変わった部分を解説します。
    まず8〜10行目、スピナー関連で使用するモジュールをインポートしておきます。
    次に15、16行目、TextViewの宣言が追加されていますが、これは、入出力欄の右端の単位を表示している部分です。メニュー操作と同時に書き換えられるように、変数として定義しています。
    そして18、19行目は初期値0を与えておくように変更しています。
    それから21行目がspinnerのインスタンス用変数定義です。

    29〜31行目、入出力欄の単位表示とスピナーのインスタンスを取得します。

    33〜49行目が、変換ボタンをクリックしたときのリスナーです。
    39〜43行目、以前は40行目の一文だけだったのですが、それだと入力欄未入力状態で変換ボタンをクリックしてしまうと、数値ではないため、エラーが出て処理が止まってしまう問題がありました。そこで、入力欄が空かどうかをチェックすることで、これを回避するようにしています。

    そして52〜72行目、これが新しく設置したスピナーでアイテムが選択されたときの処理を定義するリスナーです。
    55行目で、メニューで選択されたアイテムのインデックスを取得しています。インデックスは一番上が0で、下に行くと1づつ大きくなってゆく整数で与えられます。今回は2つしかメニューアイテムを定義していないので、0か1になるはずです。
    56〜67行目が、このインデックス番号で場合分けして処理を行うswitch文です。書式は見ての通りです。それぞれのidxの値に応じてcase**:の部分にジャンプし、break;でswitch文を抜けるようになっています。それぞれの中で、変換係数の設定と単位表示の切り替えを行っています。
    換算結果を表示するのはあくまで変換ボタンを押したとき、ということでここでは変換操作は行いません。


    以上で、出来上がり。あとは動作を確認しながら入力ミスが無いかチェックしていきます。
    うーん、想定通りにばっちり出来上がりました☆


    うん、イメージ通りにはできたのですが、それはそれとしてまだ少し不満な部分もあります。
    例えば、ドロップダウンメニューの部分。今は変換する単位が2つだからいいですが、これが3つになると、メニューアイテムは6つに増えます。単位が4つだと12通り、5つだと20通りと級数的に増えてゆきます。目的の単位をメニューから探すだけで一苦労です。
    それから、重さ、長さ、速度、等の系統ごとにドロップダウンメニューの中身が切り替わるようにしてやると、ずいぶん見やすさが違うんじゃないかと思います。
    ここまでたどり着けば、誰に見せても恥ずかしくない、立派なアプリになると思うんです。

    次回以降はこれらの課題に取り組んでいきたいと思います。


    コメント
    コメントする








       

    calendar

    S M T W T F S
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
    << October 2019 >>

    アクセスカウンタ

    合計:
    今日:
    昨日:

    selected entries

    categories

    archives

    recent comment

    • ホームページをリニューアルするの巻(19)−Googleウェブサイト翻訳ツールを組み込む
      てちくん
    • ホームページをリニューアルするの巻(19)−Googleウェブサイト翻訳ツールを組み込む
      てちくん
    • ホームページをリニューアルするの巻(19)−Googleウェブサイト翻訳ツールを組み込む
      小田きく江
    • ロリポブログでGoogleにサイトマップを登録する際の注意事項
      てちくん
    • ロリポブログでGoogleにサイトマップを登録する際の注意事項
      suraugi
    • いそべぇのペーパークラフトを作る(初級編)(12)
      てちくん
    • いそべぇのペーパークラフトを作る(初級編)(12)
      だべえ
    • noomでマイナス12kgのダイエットに成功!
      Yoko

    recommend

    recommend

    recommend

    ドール デザートメーカー ヨナナス901
    ドール デザートメーカー ヨナナス901 (JUGEMレビュー »)

    結構高いんです、でも欲しいんです!

    links

    profile

    書いた記事数:173
    最近の更新日:2017/01/30

    search this site.

    others

    mobile

    qrcode

    powered

    無料ブログ作成サービス JUGEM

    Google Adsense

    楽天ブックス

    楽天