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

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

    今回は、前回挙げた課題の前半、変換する単位と方向をまとめて1つのスピナーに入れると、組み合わせが多くなって見づらい件について、改善を図りたいと思います。

    構想はこうです。
    ・1つのスピナーで表示するのを止める。
    ・入力と出力の単位をスピナーで選べるようにする。
    ・入出力の単位に応じて自動的に換算するようにする。

    この自動的に換算するやり方は、実は簡単です。
    まず何か1つ基準の単位を決めます。例えば重さだったらkgとか。
    ここで、各単位について、これを掛けたらkgになる、という値を設定しておきます。例えばlb(ポンド)なら0.4536、「貫」なら3.75です。もちろんkgの場合は1です。
    そして入力と出力を選んだとき、例えばlbから貫に変換したいとき、まずlbの係数を掛けてkgにします。そしたら次に貫の係数で割るとkgが貫になり、無事lb→貫の換算ができると言う訳です。

    早速やってみましょう。
    レイアウトはこんな感じです。


    以前あった「入力:」「出力:」の文字は、無くても判りそうなので消しました。
    入出力エリアそれぞれに対し、単位を表示するスピナーを1つずつ設置してあります。
    xmlはこうなります。
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.example.tetsuya.unitconverter3.UnitConverter3">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:weightSum="1"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:id="@+id/linearLayout">
            <EditText
                android:layout_width="@dimen/ioWidth"
                android:layout_height="wrap_content"
                android:inputType="numberDecimal"
                android:ems="10"
                android:id="@+id/editText" />
            <Spinner
                android:layout_width="@dimen/unitWidth"
                android:layout_height="wrap_content"
                android:id="@+id/spinner"
                android:entries="@array/unit"
                android:spinnerMode="dropdown" />
        </LinearLayout>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/linearLayout"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:id="@+id/linearLayout2">
            <TextView
                android:layout_width="@dimen/ioWidth"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:text="@string/zero"
                android:id="@+id/textView" />
            <Spinner
                android:layout_width="@dimen/unitWidth"
                android:layout_height="wrap_content"
                android:id="@+id/spinner2"
                android:entries="@array/unit"
                android:spinnerMode="dropdown" />
        </LinearLayout>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/convert"
            android:id="@+id/button"
            android:layout_below="@+id/linearLayout2"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true" />
    </RelativeLayout>
    

    入出力エリアはそれぞれ単位スピナーと一緒にLinearLayoutに入れています。
    入出力エリアの幅は220dp、単位スピナーの幅は120dpの固定にしています。

    リソースも出しておきます。

    strings.xml
    <resources>
        <string name="app_name">UnitConverter3</string>
        <string name="convert">変換</string>
        <string name="zero">0.0</string>
        <string-array name="unit">
            <item>kg</item>
            <item>lb</item>
            <item>貫</item>
        </string-array>
    </resources>
    

    dimens.xml
    <resources>
        <!-- Default screen margins, per the Android Design guidelines. -->
        <dimen name="activity_horizontal_margin">16dp</dimen>
        <dimen name="activity_vertical_margin">16dp</dimen>
        <dimen name="unitWidth">120dp</dimen>
        <dimen name="ioWidth">220dp</dimen>
    </resources>
    

    こんなところです。
    ではいよいよjavaをいじっていきます。
    いきなりですが、結論はこちら。
    package com.example.tetsuya.unitconverter3;
    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 UnitConverter3 extends AppCompatActivity {
        // 使用する変数等を定義
        EditText editText;
        TextView textView;
        double convRatioInput = 1.0;
        double convRatioOutput = 1.0;
        double inputValue = 0.0;
        double outputValue = 0.0;
        String input;
        Spinner unitSpinnerInput;
        Spinner unitSpinnerOutput;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_unit_converter3);
            // 入力エリアと出力表示エリアのインスタンスを取得
            editText = (EditText) findViewById(R.id.editText);    // 入力エリア
            textView = (TextView) findViewById(R.id.textView);    // 出力エリア
            unitSpinnerInput = (Spinner) findViewById(R.id.spinner);     // 入力単位スピナー
            unitSpinnerOutput = (Spinner) findViewById(R.id.spinner2);     // 出力単位スピナー
            // 変換ボタンのオンクリックリスナーを設定
            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 * convRatioInput / convRatioOutput;
                    // 変換した数値を文字列として出力エリアにセット
                    textView.setText(String.format("%.10g",outputValue));
                }
            });
            // 入力単位spinnerのアイテムセレクトリスナーを設定
            // リスナーを登録
            unitSpinnerInput.setOnItemSelectedListener(new OnItemSelectedListener() {
                // アイテムが選択された時
                public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) {
                    int idx = unitSpinnerInput.getSelectedItemPosition();
                    switch(idx){
                        case 0: // kg
                            convRatioInput = 1.0;
                            break;
                        case 1: // lb
                            convRatioInput = 0.45359243;
                            break;
                        case 2: // 貫
                            convRatioInput = 3.75;
                            break;
                    }
                }
                // アイテムが選択されなかった
                public void onNothingSelected(AdapterView<?> parent) {
                }
            });
            // 出力単位spinnerのアイテムセレクトリスナーを設定
            // リスナーを登録
            unitSpinnerOutput.setOnItemSelectedListener(new OnItemSelectedListener() {
                // アイテムが選択された時
                public void onItemSelected(AdapterView<?> parent, View viw, int arg2, long arg3) {
                    int idx = unitSpinnerOutput.getSelectedItemPosition();
                    switch(idx){
                        case 0: // kg
                            convRatioOutput = 1.0;
                            break;
                        case 1: // lb
                            convRatioOutput = 0.45359243;
                            break;
                        case 2: // 貫
                            convRatioOutput = 3.75;
                            break;
                    }
                }
                // アイテムが選択されなかった
                public void onNothingSelected(AdapterView<?> parent) {
                }
            });
        }
    }
    

    それでは、変わったところを解説してゆきます。
    まず、15,16行目、換算係数が、インプット用とアウトプット用の2つになりました。
    20、21行目、スピナーも2つになっています。
    29、30行目、その2つのスピナーのインスタンスを取得しています。
    44行目、ここがポイントです。以前は変換係数を1つ掛けるだけでしたが、今回は、インプット用を掛けて、アウトプット用で割って換算しています。
    46行目、出力をフォーマットで出すように見直しました。「g」の識別子は、通常は小数で表示し、表示しきれないほど桁が増えたり逆に小さくなったら自動的に指数表示にしてくれる優れものです。「10」は有効数字10桁という意味です。
    51〜70行目、1つ目のスピナーのリスナーを設定しています。選ばれた単位に応じて、「それをkgに変換する係数」を設定しています。
    同様に73〜92行目で、2つ目のアウトプット側のスピナーのリスナーを設定しています、が、中身はインプット側と全く同じです。違うのはリスナーの名前だけですね。

    こうして出来上がったのがこちらです。



    単位を選んで変換をクリックするだけで、自由自在に変換してくれるようになりました。
    あとは単位を充実させてやればいいだけです。


    今回はここまで。次回は重さ、速度、長さなどのカテゴリーを選ぶと、単位のスピナーの中身が自動的に切り替わる仕組みを作っていきたいと思います。


    コメント
    コメントする








       

    calendar

    S M T W T F S
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    << November 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

    楽天ブックス

    楽天