My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
BmiLogic  
完成 BMI 程式
tw
Updated Mar 29, 2011 by gasolin

至此,我們已經完成了 bmi 程式的介面設計,並且理解了了新建立的程式。剩下我們要做的,只剩下為 BMI 程式加上程式邏輯囉。

很幸運的是,BMI 程式中用到的並不是什麼神秘的演算法,你甚至可以透過搜尋引擎找到中文的範例。

完整的程式如下:

1  package com.demo.android.bmi;
2
3  import java.text.DecimalFormat;
4
5  import android.app.Activity;
6  import android.os.Bundle;
7  import android.view.View;
8  import android.view.View.OnClickListener;
9  import android.widget.Button;
10 import android.widget.EditText;
11 import android.widget.TextView;
12
13 public class Bmi extends Activity {
14     /** Called when the activity is first created. */
15     @Override
16     public void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.main);
19
20         //Listen for button clicks
21         Button button = (Button)findViewById(R.id.submit);
22         button.setOnClickListener(calcBMI);
23     }
24
25     private OnClickListener calcBMI = new OnClickListener()
26     {
27         public void onClick(View v)
28         {
29             DecimalFormat nf = new DecimalFormat("0.00");
30             EditText fieldheight = (EditText)findViewById(R.id.height);
31             EditText fieldweight = (EditText)findViewById(R.id.weight);
32             double height = Double.parseDouble(fieldheight.getText().toString())/100;
33             double weight = Double.parseDouble(fieldweight.getText().toString());
34             double BMI = weight / (height * height);
35
36             TextView result = (TextView)findViewById(R.id.result);
37             result.setText("Your BMI is "+nf.format(BMI));
38
39             //Give health advice
40             TextView fieldsuggest = (TextView)findViewById(R.id.suggest);
41             if(BMI>25){
42                 fieldsuggest.setText(R.string.advice_heavy);
43             }else if(BMI<20){
44                 fieldsuggest.setText(R.string.advice_light);
45             }else{
46                 fieldsuggest.setText(R.string.advice_average);
47             }
48         }
49     };
50 }

我們會學到:導入其他用到的模組、如何取得介面元件、如何對按鈕設定動作。

從上面的完整程式中,我們看到上面介紹到的程式主體都還在,不過也增加了一些內容。這些內容即我們的主要程式邏輯。

講解

//Listen for button clicks

兩個反斜線是 java 語言所支援的另一種註解方式。

按鈕

Button button = (Button)findViewById(R.id.submit);

宣告一個 button 實體,透過 findViewById 方法,從資源檔中取得對應的介面元件(按鈕)。這邊取出的是「R.id.submit」按鈕元件。

「R.id.submit」對應到 XML 描述檔的資源是

<Button id="@+id/submit"
/>

為了確保宣告的型別跟 XML 描述檔中描述的介面元件型別一致,好使程式運作正常,我們在 「findViewById」 方法前加上 「(Button)」修飾,強制將取得的資源型別設成 「button」型別。

button.setOnClickListener(calcBMI);

這句包含了「Button」類別中的「setOnClickListener」方法。方法中傳入了一個「calcBMI」函式。Android 系統的 UI 互動方式採用常見的事件驅動方式。也就是當使用者按下「button」按鈕的時候,Android 系統會去觸發按鈕的「setOnClickListener」方法中所指定的「calcBMI」函式。

觸發事件函式

    private OnClickListener calcBMI = new OnClickListener() { 
        public void onClick(View v) {
            …
        }
    };

範例中所有的邏輯與運算內容,都放置在這個事件函式中。

當使用者按下按鈕時,即觸發「OnClickListener」類型的事件函式。也有人將這種函式稱為回呼(Call Back)函式,因為是當有動作做完(使用者按下了按鈕),才會呼叫(算出 BMI 值)。

onClick(View v) 是 OnClickListener 中實作的方法,代表按下按鈕時會執行的事件方法。

編輯欄位

EditText fieldheight = (EditText)findViewById(R.id.height);
EditText fieldweight = (EditText)findViewById(R.id.weight);

與上面 button 的宣告類似,只是改成宣告 EditText 實體,透過 findViewById 方法,從資源檔中取得對應的文字欄位元件。這邊取出的是「R.id.height」和「R.id.weight」文字欄位元件。

運算

double height = Double.parseDouble(fieldheight.getText().toString())/100;
double weight = Double.parseDouble(fieldweight.getText().toString());
double BMI = weight / (height * height);

BMI 值的算法是「體重除以身高的平方」。 用計算式來表示,就是

體重(weight) / 身高(height)*身高(height)

這麼看來,上面的程式碼就很清晰了。我們先從身高欄位(fieldheight)、體重欄位(fieldweight)中取得使用者輸入的身高體重數字,再定義一個雙倍精度幅點數(double) 型態的變數 BMI 來儲存運算的結果,因此,BMI 變數中儲存了運算出來的實際 BMI 值。

顯示結果

我們把 BMI 值運算出來了,接著要將結果顯示回螢幕上。

TextView result = (TextView)findViewById(R.id.result);

為了將結果顯示到螢幕上,在之前 XML 定義檔中我們已經預留了一個名為「result」的 TextView 欄位。在程式碼中,我們再宣告一個 TextView 實體,透過 findViewById 方法,從資源檔中取得對應的介面元件(文字顯示)。這邊取出的就是「R.id.result」介面元件。

DecimalFormat nf = new DecimalFormat("0.00");
result.setText("Your BMI is "+nf.format(BMI));

透過 java 內建的 DecimalFormat 函式,我們可以將運算結果,以適當的格式顯示。

透過「setText」方法,我們可以將指定的字串,顯示在螢幕上文字類型的介面元件中。

顯示建議

「顯示建議」的方式與「顯示結果」完全相同,只有多加了幾個「if」判斷式:當BMI 值大於25顯示過重,小於20顯示過輕。程式碼留給讀者自習。

//Give health advice
TextView fieldsuggest = (TextView)findViewById(R.id.suggest);
if(BMI>25){
    fieldsuggest.setText(R.string.advice_heavy);
}else if(BMI<20){
    fieldsuggest.setText(R.string.advice_light);
}else{
    fieldsuggest.setText(R.string.advice_average);
}

完整的 BMI 程式動作流程,就是使用者在身高體重欄位中輸入好身高體重後,按下「計算 BMI 值」按鈕,程式根據識別符號,從對應的身高體重欄位讀取輸入的值,並做計算,最後將計算的結果與建議顯示到螢幕上。

< 解讀程式流程 | 回目錄 | 重構程式 >


對於本章,您還期望知道什麼樣的內容呢?請在下方提出建議!

Comment by xiaobrah...@gmail.com, Jun 12, 2008

GOOD!

Comment by anshan....@gmail.com, Sep 18, 2008

quite well

Comment by Brooke...@gmail.com, Feb 24, 2009

I think It is a good tutorial for new learner. thanks for your kindness.

Comment by kwi...@gmail.com, Feb 26, 2009

thanks for your help. your tutorial is very helpful.

Comment by hoh...@gmail.com, Mar 5, 2009

怎么没有具体说明OnClickListener?这个内部类的程式码呢?

Comment by nrg19840409, May 16, 2009

很好的新手教程啊 感谢

Comment by pail....@gmail.com, May 25, 2009

我模拟器上运行了这个bmi程式后,在输入体重和身高的时候,虚拟键盘自动出来了,方便输入后,点击button计算后,虚拟键盘并不会自动消失。 请问,如何让虚拟键盘消失呢?

Comment by project member gasolin, May 25, 2009

pail.jin; 按 Menu 鍵吧

Comment by hebingYY...@gmail.com, Jun 3, 2009

有widget方面的吗?

Comment by project member gasolin, Jun 3, 2009

hebingYYDog, 這教程看完應該就可以看懂官方文件啦 :)

Comment by col...@gmail.com, Jul 10, 2009

20 //Listen for button clicks 21 Button button = (Button)findViewById(R.id.submit); 22 button.setOnClickListener(calcBMI); 23 } 24 25 private OnClickListener? calcBMI = new OnClickListener?() 26 { 27 public void onClick(View v) …… 可以先使用calcBMI 后定义吗? 有点不理解

Comment by arthu...@gmail.com, Aug 4, 2009

這書是好的,但是我照抄居然會錯,我太笨

Comment by WenYuan....@gmail.com, Aug 7, 2009

雖然已是程式老手,新接觸Android的我還是需要、想要這樣一份清楚詳細的初級教學。 我會繼續逐字研讀,感謝分享。

Comment by how2...@gmail.com, Aug 21, 2009

Android因為有您的無私一定會更加拙壯,鉅細靡遺,感謝!!

Comment by bakal...@gmail.com, Sep 9, 2009

很詳細的教學,感謝你的分享.

Comment by nullme....@gmail.com, Sep 11, 2009

雖然已經會寫Java,工作也跟J2EE息息相關。 您寫的說明超容易入門,我要多學習。

Comment by zhik...@gmail.com, Sep 21, 2009

我在模擬器和真機上測試,在界面輸入身高、體重,提交數據時,程序出錯停止了。請教

Comment by project member gasolin, Sep 21, 2009

zhikook, 去比較 http://code.google.com/p/androidbmi/source/list 裡的原始碼看看輸入有什麼問題

Comment by new126r...@126.com, Oct 2, 2009

有点不明白OnClickListener?对象的onClick()方法 和按钮的setOnClickListener() 方法是如何配合运行的,按非OOP思维(年初才开始学JAVA,以前只做过Power Builder项目)给按钮对象定义或重载一个onClick()方法就行了,其他的事交给系统处理,系统会自动捕捉点击事件,捕捉到之后会自动调用onClick()方法,PB中还可以按点击的鼠标左、中、右键及左中右键的组合方式的不同来分开执行onClick()方法,例如按住Ctrl键同时按鼠标左键与单独按鼠标左键(或同时按下鼠标左键与右键)就会执行不同代码产生不同效果(如果代码中有不同处理的话)

Android 的 API 文档看着就犯晕,不如JavaFX的API文档写的好,也许是个人阅读习惯的问题

Comment by e...@live.cn, Oct 15, 2009

好棒,一次成功!

Comment by liuzhu...@gmail.com, Dec 2, 2009

为什么我敲入文中的代码,显示 The type new View.OnClickListener?(){} must implement the inherited abstract method View.OnClickListener?.onClick(View)的错误。

Comment by project member gasolin, Dec 2, 2009

所以要繼續把 onClick(View v) 敲進去....

Comment by liuzhu...@gmail.com, Dec 2, 2009
昨天因为不小心把onClick的o敲成O了,所以报抽象接口中的方法没有实现的错误。后面同学给我给我说了一个Eclipse的快捷键可以避免这中错误。在将光标放在OnClickListener?的大括号中,按alt+shif+s,就会出现必须OnClickListener?必须实现的方法,选择出现的方法,在Eclipse会在大括号中添加此方法,自己在实现这个方法就可以。多谢gasolin的回复
Comment by edwar12...@gmail.com, Jan 4, 2010

回: Comment by liuzhu145, Dec 02, 2009 为什么我敲入文中的代码,显示 The type new View.OnClickListener??(){} must implement the inherited abstract method View.OnClickListener??.onClick(View)的错误。

答: 出现下面这个错误是因为你没有导入 所需全部的包。 The type new View.OnClickListener?(){} must implement the inherited abstract method

View.OnClickListener?.onClick(View)

解决办法: Ctrl+A -> Ctrl + Shift + O

Comment by JHS.John...@gmail.com, Jan 8, 2010

每周来这里至少3次,多谢分享~!

Comment by taican....@gmail.com, Jan 21, 2010

請教各位大大:

public void onClick(View v) 是甚麼意思呢?

感謝!

Comment by project member gasolin, Feb 10, 2010

本文中更新了解釋 :)

Comment by redflo...@gmail.com, Mar 16, 2010

想請問宣告那些字的顏色是怎麼修改的 Button button = (Button)findViewById(R.id.submit); 我的Button還是黑色的 不像文章中是紫色的 設定調很久調不出來 黑色實在不易閱讀>< 謝謝

Comment by project member gasolin, Mar 17, 2010

這是文件才有的功能....eclipse 上應該顏色會不一樣

Comment by mikeZhu1...@gmail.com, Mar 21, 2010

写的非常好的,适合入门开发Android application的教材,谢谢详细的分析。

Comment by zodiac...@gmail.com, Apr 25, 2010

double height = Double.parseDouble(fieldheight.getText().toString()) 发现报错的原因了,原来我打少了getText()这个方法。

Comment by zhao.yu....@gmail.com, May 13, 2010

向问一下,那个虚拟键盘不会自动消失的问题!!! 我模拟器上运行了这个bmi程式后,在输入体重和身高的时候,虚拟键盘自动出来了,方便输入后,点击button计算后,虚拟键盘并不会自动消失。请问,如何让虚拟键盘消失呢?

Comment by project member gasolin, May 13, 2010

按模擬器上的 Back 鍵

Comment by zz.kevi...@gmail.com, May 14, 2010

It is very good for a new leaner

Comment by lp43si...@gmail.com, May 27, 2010

這真的是一份有內容、也一一解釋的電子文檔,期待新版2.2的更新! :)

Comment by sunny.ju...@gmail.com, Jun 2, 2010

我也買了你的書! 真是本很棒的入門書~

Comment by sleimu0...@gmail.com, Jun 29, 2010

請問 android 要怎麼使用變數? 例如 int x=5; 後面如果遇到某些條件 x=10; 但是我試 一開始x=5就是5了 不會再變耶?

Comment by nigs...@gmail.com, Sep 4, 2010

为什么我敲入文中的代码,显示 The type new View.OnClickListener???(){} must implement the inherited abstract method View.OnClickListener???.onClick(View)的错误。 包已经全部导入了。。。ctrl+shift+o没用

Comment by nigs...@gmail.com, Sep 4, 2010

已经解决了,貌似剪切复制一下就可以了。。。。这属于什么错误阿。。

Comment by cusso...@gmail.com, Sep 11, 2010

入不了點數? 是不是因為.. TEXTEDIT 限制了數字的原故?

Comment by holala....@gmail.com, Sep 20, 2010

模擬器上可以執行 但是在android 手機上卻無法安裝 已經加了 <uses-sdk android:minSdkVersion="7" /> 還是不行 有解嗎?

Comment by project member gasolin, Sep 20, 2010

手機上要把 debug mode 打開

Comment by sky...@hotmail.com, Sep 22, 2010

Thanks a lot!獲益良多!

Comment by liulanch...@gmail.com, Sep 23, 2010

模拟器上执行报错了"The application BMI(process com.demo.android.bmi)has stopped unexpectedly." 调试 程序最后一行下了断点 step over后就来到了Thread[<1>main](Suspended (exception NullPointerExecption?)) 这个...空指针异常? 再一次step over后Thread就到了InvocationTargetException?.<init>(Throwable)line:50 而这个class 却显示Source not found... 请gasolin帮忙解答下 谢谢啦~

Comment by project member gasolin, Sep 23, 2010

執行有誤時請先 check out 一份 Source 下來對照

Comment by ktu...@gmail.com, Nov 6, 2010

this is helpful thx a lot

Comment by dcd1...@gmail.com, Feb 23, 2011

good

Comment by seraph.z...@gmail.com, Feb 23, 2011

第一個簡易ap完成了,感謝您無私的教學~

Comment by rachel.q...@gmail.com, Mar 8, 2011

大家千万注意大小写。onClickListener和OnClickListener?是不一样的。findviewbyid和findViewByid也是不一样的。

Comment by rachel.q...@gmail.com, Mar 8, 2011

另外请多讲一讲onClick(View v)这个方法。 谢谢。

Comment by cyts...@gmail.com, Mar 29, 2011

第一次學 Android, 看了一堆的書, 沒有這裡的資料說明的好 再次感謝作者的辛苦和用心

這裡有一個 but 回覆一下 程式碼 41 ~ 47 裡有需要小小的修改, 如下

if (BMI > 25) {
fsuggest.setText(R.string.advice_heavy);
} else if (BMI > 20 && BMI <= 25) {
fsuggest.setText(R.string.advice_average);
} else {
fsuggest.setText(R.string.advice_light);
}

主要是 else if 後面那裡 這樣子才能真正的判斷出過輕的BMI值

Comment by AlvinCha...@gmail.com, Mar 30, 2011

謝謝分享 但是請問有完整的main.xml檔嘛 因為我這個新手還不太會敲出"EditText"和"TextView"和"Button"這些部分!! 謝謝您

Comment by jimmy0...@gmail.com, Apr 10, 2011

讚!!!

附帶一提, 我有買您的書"Google!Android 2手機應用程式設計入門第三版", 我看到 ch11-3 講解部份, 對於"按鈕" 的解釋覺得有些疑惑,書本提到:

Button button = (Button)findViewById(R.id.submit);
宣告一個「Button」實體, 宣告「Button」時需要先匯入Button類別:

以上那段敘述是否應改為如下比較正確?

宣告一個「button」實體, 宣告「button」時需要先匯入Button類別:

標準的java 宣告方式不是如下這樣嗎? 類別名稱 變數實體= new 類別名稱(); 所以, 第一個欄位是類別名稱, 第二個欄位才是變數實體名稱吧?

Comment by project member gasolin, Apr 10, 2011
jimmy0..., 謝謝您的建議,確實這樣寫會比較清楚,我盡量改正 :)
Comment by johammis...@gmail.com, Apr 30, 2011

您好, 請問一下此行程式碼: Button button = (Button)findViewById(R.id.submit); Button是一個類別, 會何不需要用new來產生物件(button), 就能直接使用 "=" 來使用方法?

Comment by project member gasolin, Apr 30, 2011

因為findViewById函式會根據識別代號返回一個「View」介面元件實體,使用「(Button)」強制將這個介面實體轉型為Button類別的實體

Comment by johammis...@gmail.com, May 1, 2011

謝謝你的回答。 再請問一下findViewById這個方法,要去Android Dev的哪裡查看呢?

Comment by project member gasolin, May 1, 2011
johammis...: google it
Comment by jack...@gmail.com, May 3, 2011

想請問 32 double height = Double.parseDouble(fieldheight.getText().toString())/100; 33 double weight = Double.parseDouble(fieldweight.getText().toString());

第32行跟第33行不都是取得User所輸入的值嗎,那第32行後面為什麼要多"/100"呢?差別在?

Comment by u8812012...@gmail.com, Jun 1, 2011

jack ... 身高的單位要轉換為公尺

Comment by celia7...@gmail.com, Aug 28, 2011

請問~輸入完整個程式,33行的double weight = Double.parseDouble(fieldweight.getText().toString()); 卻出現fieldweight cannot resolved,一直找不道原因,請問問題是出在哪邊呢?? 謝謝!

Comment by kench...@gmail.com, Oct 26, 2011

想請問~ 若果 height 或 weight 其中一個或兩個都留空不輸入, 程式就會 force close, 請問是什麼原因喔?

Comment by project member gasolin, Oct 26, 2011
kench..., 繼續看下去後面有講
Comment by u09900...@lssh.tp.edu.tw, Nov 16, 2011

請問public void onClick(View v)裡的"v"是什麼呢?

Comment by lamanch...@gmail.com, Feb 5, 2012

A:當輸入身高體重為空值時候,執行計算bmi會導致app crash. 可以增加判斷: if (fieldheight.getText().toString().equals("")|fieldweight.getText().toString().equals("")){

result.setText("請輸入身高以及體重數值");
}else{ 確定有輸入數值之後要做的事情 }
B:輸入的身高體重不能為0,也會造成問題,所以要加入判斷輸入值是否為0

Comment by jameslia...@gmail.com, Feb 28, 2012

BMI公式好像有問題..以書上例子170cm..76kg bmi=weight/(height*height)=76/(170*170)=0.00262975 依程式if(BMI<20){

fieldsuggest.setText(R.string.advice_light);}
這樣會是很瘦的人耶...若把身高單位改成公尺的話....依BMI公式計算.所得出來值.26..就符合情況 但是 介面的身高欄位..卻不能輸入小數點...感覺就很矛盾..

Comment by jameslia...@gmail.com, Feb 28, 2012

更正..漏看到height 有除以100...

Comment by project member gasolin, Feb 28, 2012

所以身高要先除以100換算成公尺阿...範例之所以是範例,就是會有下面的版本繼續改進第一版範例阿:)

Comment by s901056...@gmail.com, Apr 11, 2012

27 public void onClick(View v) 請問 第27行的這句code onClick括弧裡面為什麼是打Viwe v?

View v 所指的又是什麼?

另一個問題是 32 double height = Double.parseDouble(fieldheight.getText().toString())/100; 33 double weight = Double.parseDouble(fieldweight.getText().toString());
Double 改成用Int 的話要怎麼改?

Comment by project member gasolin, Apr 11, 2012

s901056789, 學到這邊,一些細節不懂照著用也是沒什麼關係的。您問的問題都屬於程式(Java)相關基礎,因為主題問題,請自行去補充相關知識吧~


Sign in to add a comment
Powered by Google Project Hosting