zoukankan      html  css  js  c++  java
  • 【Android入门】融会贯通篇:结合上一个实例增加新技巧

    一、新建针对美国、英国用户的BMI 

    • 改造计划

    1. 以原 BMI 应用程序为基础;
    2. 精简界面,只留下必要的功能;
    3. 将界面与文字消息由中文改成英文,以符合目标用户特性;
    4. 将计量单位由公制改为英制,并修改相关表达式;
    5. 改进身高的输入方式,由原本用一个“文字编辑文本框”(TextEdit)输入身高,改成用两个“下拉菜单”(Spinner)选择身高英尺、英寸。

    res/layout/activity_main.xml

    这里暂时使用前面“BMI”应用程序用到的“文字编辑字段”来直接输入英尺、英寸,以后再用下拉菜单组件来替换这两个字段

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        tools:context=".MainActivity">
    
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/us_height" />
        
        <EditText
            android:id="@+id/feet"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="" />
    
        <EditText
            android:id="@+id/inch"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="" />
    
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/pound"/>
    
        <EditText
            android:id="@+id/weight"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:inputType="numberDecimal" />
    
        <Button
            android:id="@+id/submit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/bmi_btn"/>
    
        <TextView
            android:id="@+id/result"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:text="" />
    
        <TextView
            android:id="@+id/suggest"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="" />
    
    </LinearLayout>

    res/value/string.xml

    <resources>
        <string name="app_name">aBMI</string>
        <string name="app_label">BMI for the  British system</string>
        <string name="us_height">Height</string>
        <string name="feet_prompt">Select Feet</string>
        <string name="inch_prompt">Select Inches</string>
        <string name="pound">Weight (lbs)</string>
        <string name="bmi_btn">Calc BMI</string>
        <string name="bmi_result">Your BMI is ...</string>
        <string name="input_error">oops,you should type numbers only</string>
        <string name="advice_light">You should eat more</string>
        <string name="advice_average">You are in good shape,keep it!</string>
        <string name="advice_heavy">You should lose some weight</string>
        <string name="advice_fat">You should do something to improve your situation,right now</string>
        <string name="about_label">About...</string>
        <string name="about_title">About aBMI 1.0</string>
        <string name="about_msg">aBMI is a BMI calculator for the British system,written by sc</string>
        <string name="ok_label">OK</string>
    
        <string-array name="feets">
            <item>2 feet</item>
            <item>3 feet</item>
            <item>4 feet</item>
            <item>5 feet</item>
            <item>6 feet</item>
            <item>7 feet</item>
            <item>8 feet</item>
        </string-array>
        <string-array name="inches">
            <item>0 inches</item>
            <item>1 inches</item>
            <item>2 inches</item>
            <item>3 inches</item>
            <item>4 inches</item>
            <item>5 inches</item>
            <item>6 inches</item>
            <item>7 inches</item>
            <item>8 inches</item>
            <item>9 inches</item>
            <item>10 inches</item>
            <item>11 inches</item>
        </string-array>
    </resources>

    MainActivity.java

     在“aBMI应用程序”中,我们只保留了“关于...”(MENU_aBOUT)的选项,把另一个“结束”的选项移除了。在“关于...”页面中,也将连接首页的按钮移除了。

    package com.demo.android.abmi;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    import java.text.DecimalFormat;
    
    //aBMI is for British system
    public class MainActivity extends Activity {
        private static final String TAG = "aBmi";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            findViews();
            setListensers();
        }
    
        private Button button_calc;
        private EditText field_feet;
        private EditText field_inch;
        private EditText field_weight;
        private TextView view_result;
        private TextView view_suggest;
    
        private void findViews() {
            Log.d(TAG, "find Views");
            button_calc = (Button) findViewById(R.id.submit);
            field_feet = (EditText) findViewById(R.id.feet);
            field_inch = (EditText) findViewById(R.id.inch);
            field_weight = (EditText) findViewById(R.id.weight);
            view_result = (TextView) findViewById(R.id.result);
            view_suggest = (TextView) findViewById(R.id.suggest);
        }
    
        //Listen for button clicks
        private void setListensers() {
            Log.d(TAG, "set Listensers");
            button_calc.setOnClickListener(calcUsBMI);
        }
    
        private Button.OnClickListener calcUsBMI = new Button.OnClickListener() {
            @Override
            public void onClick(View view) {
                DecimalFormat nf = new DecimalFormat("0.00");
                try {
                    double height = (Double.parseDouble(field_feet.getText().toString())*12+Double.parseDouble(field_inch.getText().toString()))*2.54/100;
                    double weight = Double.parseDouble(field_weight.getText().toString())*0.45359;
                    double BMI = weight / (height * height);
                    //Present result
                    view_result.setText(getText(R.string.bmi_result) + nf.format(BMI));
    
                    //Give health advice
                    if(BMI > 27) {
                        view_suggest.setText(R.string.advice_fat);
                    } else if(BMI > 25) {
                        view_suggest.setText(R.string.advice_heavy);
                    } else if(BMI < 20) {
                        view_suggest.setText(R.string.advice_light);
                    } else {
                        view_suggest.setText(R.string.advice_average);
                    }
                } catch (Exception obj) {
                    Toast.makeText(MainActivity.this, getString(R.string.input_error), Toast.LENGTH_SHORT).show();
                }
            }
        };
    
        protected static final int MENU_ABOUT = Menu.FIRST;
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);
            Log.d(TAG, "open Menu");
            menu.add(0, MENU_ABOUT, 0, R.string.about_label);
            return true;
        }
    
        public boolean onOptionsItemSelected(MenuItem item) {
            super.onOptionsItemSelected(item);
            Log.d(TAG, "select Menu Item");
            switch (item.getItemId()) {
                case MENU_ABOUT:
                    openOptionsDialog();
                    break;
            }
            return true;
        }
    
        private void openOptionsDialog() {
            Log.d(TAG, "open Dialog");
            new AlertDialog.Builder(this)
                    .setTitle(R.string.about_title)
                    .setMessage(R.string.about_msg)
                    .setPositiveButton(R.string.ok_label,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                }
                            })
                    .show();
        }
    }

    二、支持多国语言

      要让应用程序支持多个语言界面,不需要置换原有的语言界面。只需要在“res”目录下新建相应的语言目录,新建“res/values-en”来放“英文字符串”,新建“res/values-zh-rCN”来放“简体中文字符串”。

    以“简体中文字符串”的“values-zh-rCN”目录名称命名方式为例,“zh”是主语系,“h”代表“中文”。“r”字母之后的“CN”是分支,表示“简体中文”。“r”是“revision”的意思。

    values-zh-rCN/strings.xml

    <resources>
        <string name="app_name">aBMI</string>
        <string name="app_label">BMI 英制计算器</string>
        <string name="us_height">身高</string>
        <string name="feet_prompt">选择英尺</string>
        <string name="inch_prompt">选择英寸</string>
        <string name="pound">体重 (lbs)</string>
        <string name="bmi_btn">计算 BMI 值</string>
        <string name="bmi_result">你的 BMI 值是</string>
        <string name="input_error">哦哦,字段中只能输入数字喔</string>
        <string name="advice_light">你该多吃点</string>
        <string name="advice_average">你的体型很不错喔,好好保持吧!</string>
        <string name="advice_heavy">你应该减肥啰!</string>
        <string name="advice_fat">为了健康,你应该马上采取一些行动啰!</string>
        <string name="about_label">关于...</string>
        <string name="about_title">关于 aBMI 1.0</string>
        <string name="about_msg">aBMI 是个 BMI 值计算器程序,由 sc 编写</string>
        <string name="ok_label">OK</string>
    
        <string-array name="feets">
            <item>2 英尺</item>
            <item>3 英尺</item>
            <item>4 英尺</item>
            <item>5 英尺</item>
            <item>6 英尺</item>
            <item>7 英尺</item>
            <item>8 英尺</item>
        </string-array>
        <string-array name="inches">
            <item>0 英寸</item>
            <item>1 英寸</item>
            <item>2 英寸</item>
            <item>3 英寸</item>
            <item>4 英寸</item>
            <item>5 英寸</item>
            <item>6 英寸</item>
            <item>7 英寸</item>
            <item>8 英寸</item>
            <item>9 英寸</item>
            <item>10 英寸</item>
            <item>11 英寸</item>
        </string-array>
    </resources>
    • “values”目录名称,与改写后对应的支持语言关系如下
    1. 繁体中文:values-zh-rTW
    2. 简体中文:values-zh-rCN
    3. 日文:values-ja
    4. 英文:values-en
    5. 美式英文:values-en-rUS
    6. 英式英文:values-en-rUK
    • 切换语言

      切换手机设置的语言,应用程序会改成对应的语言

    三、使用接口(Adapter)

      接口:负责转换数据源提供给界面组件的函数

      Android平台,不允许直接将字符串数组应用在界面组件中。界面菜单的项目,都得要靠接口来提供,这样做是“为了保持程序的弹性”。Android平台默认提供的接口类型有很多种,“ArraryAdapter”的作用是读入程序中已声明的数组,并转换成界面组件看得懂的接口组件。还有“SimpleAdapter”(从XML文字字符串文件读入数组)、“CursorAdapter”(从ContentProvider读入数组)等。

    • 数组接口(ArrayAdapter)与字符串数组

    我们可以将字符串数组写入“res/values/string.xml”字符串文件,在“<resource>”标签中添加如下语句:

    <resources>
        ...
        <string-array name="feets">
            <item>2 feet</item>
            <item>3 feet</item>
            <item>4 feet</item>
            <item>5 feet</item>
            <item>6 feet</item>
            <item>7 feet</item>
            <item>8 feet</item>
        </string-array>
        <string-array name="inches">
            <item>0 inches</item>
            <item>1 inches</item>
            <item>2 inches</item>
            <item>3 inches</item>
            <item>4 inches</item>
            <item>5 inches</item>
            <item>6 inches</item>
            <item>7 inches</item>
            <item>8 inches</item>
            <item>9 inches</item>
            <item>10 inches</item>
            <item>11 inches</item>
        </string-array>
    </resources>

    “string-array”组件可以提供“R.array.标识符”格式的参考资源。

    在“MainActivity.java”文件中,定义“ArrayAdapter”

    private void findViews() {
        ...
           ArrayAdapter<CharSequence> adapter_feet = ArrayAdapter.createFromResource(this, R.array.feets, android.R.layout.simple_spinner_item);
           adapter_feet.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    
           ArrayAdapter<CharSequence> adapter_inch = ArrayAdapter.createFromResource(this, R.array.inches, android.R.layout.simple_spinner_item);
           adapter_inch.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        }

      “ArrayAdapter”接口使用“createFromResource”函数,接受3个参数。第1个参数是指定Activity,第2个参数指定“String.xml”字符串资源,第3个参数“android.R.layout.simple_spinner_item”为Android内置的默认下拉菜单选项格式。

      “setDropDownViewResource”方法用来定义下拉查看菜单(DropDownView)的格式

    四、添加下拉菜单组件(Spinner)

    修改 “res/layout/activity_main.xml”,添加Spinner

    ...
        <Spinner
            android:id="@+id/feet"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:drawSelectorOnTop = "true"
            android:prompt="@string/feet_prompt" />
    
        <Spinner
            android:id="@+id/inch"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:drawSelectorOnTop = "true"
            android:prompt="@string/inch_prompt" />
    ...

      我们将原本使用“TextEdit”界面组件的“@+id/feet”、“@+id/inch”两个字段,改为使用“Spinner”界面组件。

      android:drawSelectorOnTop = "true" 属性的作用是指定这个下拉菜单是否可以显示在其他菜单的上层。这个属性只有在多层菜单上才会显示出效果

      android:prompt 属性的作用是指定下拉菜单弹出菜单选项的提示语句(弹出菜单选项的标题)。

    MainActivity.java

    ...
    //    private EditText field_feet;
    //    private EditText field_inch;
        private Spinner field_feet;
        private Spinner field_inch;
    ...
    
        private void findViews() {
            ...
    //        field_feet = (EditText) findViewById(R.id.feet);
    //        field_inch = (EditText) findViewById(R.id.inch);
            field_feet = (Spinner) findViewById(R.id.feet);
            field_inch = (Spinner) findViewById(R.id.inch);
            ...
    
            ArrayAdapter<CharSequence> adapter_feet = ArrayAdapter.createFromResource(this, R.array.feets, android.R.layout.simple_spinner_item);
            adapter_feet.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            field_feet.setAdapter(adapter_feet);
    
            ArrayAdapter<CharSequence> adapter_inch = ArrayAdapter.createFromResource(this, R.array.inches, android.R.layout.simple_spinner_item);
            adapter_inch.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            field_inch.setAdapter(adapter_inch);
        }
    
        //Listen for button clicks
        private void setListensers() {
            ...
            field_feet.setOnItemSelectedListener(getFeet);
            field_inch.setOnItemSelectedListener(getInch);
            ...
        }
    
        private int feet;
        private int inch;
    
        private Spinner.OnItemSelectedListener getFeet = new Spinner.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView parent, View v, int position, long id) {
                feet = parent.getSelectedItemPosition() + 2;
            }
            public void onNothingSelected(AdapterView parent) {
            }
        };
        private Spinner.OnItemSelectedListener getInch = new Spinner.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView parent, View v, int position, long id) {
                inch = parent.getSelectedItemPosition() + 1;
            }
            public void onNothingSelected(AdapterView parent) {
            }
        };
    
        private Button.OnClickListener calcUsBMI = new Button.OnClickListener() {
            @Override
            public void onClick(View view) {
              ...
                    double height = (feet * 12 + inch) * 2.54 / 100;
                    double weight = Double.parseDouble(field_weight.getText().toString())*0.45359;
                    double BMI = weight / (height * height);
                    //Present result
                    view_result.setText(getText(R.string.bmi_result) + nf.format(BMI));
              ...
            }
        };
      ...
    }        

      在“findViews”函数中,声明了“field_feet”、“field_inch”两个“Spinner”界面组件,和“adapter_feet”、“adapter_inch”两个接口。最后“field_feet”组件加上“setAdapter”函数,将界面组件与接口接在一起,这样下拉菜单(Spinner)通过接口显示String.xml定义的数组。

      在“setListensers”函数中,“field_feet”下拉菜单的“setOnItemSelectedListener”方法负责设置按下“Spinner”菜单后续动作的函数,范例中方法参数“getFeet”函数来完成进一步的处理。

      自定义函数“getFeet”函数,函数类型“Spinner.OnItemSelectedListener”,在“OnItemSelectedListener”里面定义一个“onItemSelected”函数与另一个“onNothingSelected”函数。

      “onItemSelected”函数默认传入参数有4个,第1个参数是你当前操作的下拉菜单实体“Spinner”;第2个参数对于手机App开发用处不大;第3个参数是“Spinner”选项选中的位置,一般自上而下从0开始;第4个参数是你选中的某个Spinner中的某个下来值所在的行,也是自上而下从0开始,一般只有在从数据表中取得的数据时,才会使用到。

    本例语句“feet = parent.getSelectedItemPosition() + 2;”,“getSelectedItemPosition()”获取的“position”从0开始。而我们的项目“string-array”从“2 feet”开始,值从2开始。为了方便计算“feet 变量”,所以“+2”,这样以后存储的“feet 变量”的值就从2开始。

      “onNothingSelected”函数则是处理用户什么选项都没有选的情况。当我们将函数内容留下空白,表示当用户什么选项都没选时,不作处理。

  • 相关阅读:
    理解“统一编址与独立编址、I/O端口与I/O内存” arm
    JS + CSS 美化 select 下拉框表单
    关于 ecshop common.js 文件 自动随机输出 Powered by ECShop
    Zend Framework 入门随笔 配置与注意事项
    Delphi编程保存数据到Excel文件(4):使用NativeExcel2控件
    ORACLE 最大连接数的问题1
    一生delphi编程经验(转)
    XLSReadWriteII控件来完成10×10的乘法表
    Delphi 动态调整打印机纸张大小
    Linux下Oracle重启和修改连接数3
  • 原文地址:https://www.cnblogs.com/Rain2017/p/11219580.html
Copyright © 2011-2022 走看看