天天看點

《Android應用開發攻略》——1.15 程式:Android OS下的小費電腦Tipster

sunit katkar

1.15.1 問題

當你和朋友前往飯店就餐并且希望計算各自的賬單和小費時,可能陷入許多手動計算和分歧之中。你希望使用一個應用程式,簡單地将小費比例加到總額上,并且按照就餐人數配置設定。tipster就是android中的一個實作,用它展示一個完整的應用程式。

1.15.2 解決方案

這是一個簡單的練習,使用android中的基本gui元素,然後用一些簡單的計算和事件驅動ui代碼将它們組合起來。将用到如下gui元件:

tablelayout

該元件很好地提供了對螢幕布局的控制。可以使用html的table标記來設計視窗部件。

tablerow

這個元件定義了tablelayout中的一行。類似于html tr和td标記的組合。

textview

這個view子類為螢幕上顯示的靜态文本提供标簽。

edittext

這個view子類提供輸入用的文本字段。

radiogroup

組合單選按鈕。

radiobutton

提供單選按鈕

button

正常按鈕。

view

将使用view建立具有特定高度和顔色屬性的視覺分隔符。

1.15.3 讨論

android用xml檔案來設計視窗部件的布局。在示例項目中,eclipse的android插件生成用于布局的main.xml檔案。該檔案包含基于xml的不同視窗部件及其容器的定義。

strings.xml檔案包含應用程式中的所有字元串資源。預設的icon.png檔案用于應用程式圖示。

然後是自動生成的r.java檔案(修改main.xml時将會更新)。這個檔案包含為每個布局和視窗部件定義的常量。不要手動編輯該檔案;當修改xml檔案時,插件會自動進行相應的修改。

在例子中,tipster.java是用于activity的主java檔案。

攻略1.4和各種google教程強調了該插件的使用方法。使用eclipse插件,建立android項目tipster。最終的結果将是外觀類似于圖1-39的項目布局。

建立布局并放置視窗部件

本攻略的最終目标是建立一個類似于圖1-39的布局。

對于這個螢幕布局,将使用如下布局和視窗部件:

提供對螢幕布局的控制。這個布局使用html table标記範例來設計視窗部件的布局。

定義tablelayout中的行,類似于html tr和td标記的組合。

這個view子類提供輸入數值的文本字段。

提供單選按鈕。

使用view類建立具有特定高度和顔色屬性的視覺分隔符。

因為你所建構的應用程式中将大量使用這些視窗部件,是以要自己動手熟悉它們。當你檢視布局和視窗部件的javadoc時,仔細觀察xml屬性。這将幫助你建立main.xml布局檔案中的用法與通路該檔案的java代碼(tipster.java和r.java)之間的關聯。

eclipse adt還有一個可視化布局編輯器,以及單獨的ui工具droiddraw,這兩者都可以通過從工具面闆上拖放視窗部件來建立布局,就像所有表單設計工具一樣。但是,我建議你手動地在xml中建立布局,至少在android的初學階段要這麼做。以後,當你學習到xml布局api的微妙之處,可以将這一任務交給上述工具。

布局檔案main.xml包含布局資訊(見例1-6)。tablerow部件在tablelayout中建立一行,可以使用任意多個tablerow。在這個教程中,将使用8個tablerow,其中5個用于按鈕下面視覺分隔符之上的視窗部件,另外三個用于按鈕和分隔符之下的結果區域。

例1-6:/res/layout/main.xml

tablelayout與tablerow

研究main.xml之後,你會發現tablelayout和tablerow的使用很簡單:建立tablelayout,然後插入tablerow。現在,可以自由地在tablerow中插入任何其他視窗部件,例如textview、editview等。

仔細觀察屬性,特别是android:stretchcolumns、android:layout_column和 android:layout_span,可以用這些屬性,按照使用正常html表格的方法放置視窗部件。我建議你關注這些屬性的連結,研究它們對tablelayout的影響。

控制輸入值

控制輸入值:檢視main.xml檔案中①處的edittext部件。這是第一個文本輸入字段,用于輸入賬單“總額”,隻允許輸入數字。可以接受小數,因為真正的飯店賬單都包含元和分,而不僅僅是元。是以将android:numeric屬性值類型設定為decimal。這樣,該輸入字段中允許輸入整數值(如10)和小數值(如10.12),而不允許其他任何類型的輸入。

這是簡單明了的輸入值控制方法,可以省去在tipster.java檔案中編寫驗證代碼的麻煩,確定使用者不會輸入不正确的值。android基于xml的限制功能相當強大而實用。你應該研究特定視窗部件的所有可能屬性,從設定限制的xml快捷方法中獲得最大的益處。除非我在這個版本中完全沒有用到,否則我希望在未來的版本中,android能考慮在android:numeric加入範圍,便于我們定義接受的數值範圍。

因為(據我所知)目前還沒有範圍屬性,以後你将會看到,我們必須檢查特定的值(如0或者空值),以確定小費計算不會失敗。

分析tipster.java

現在,我們來看看控制應用程式的tipster.java檔案。這是一個主類,完成布局、事件處理和應用程式邏輯。

android eclipse插件在項目中建立tipster.java檔案的預設代碼如例1-7所示。

例1-7:/src/com/examples/tipcalc/tipster.java的代碼段1

tipster類擴充了android.app.activity類。活動(activity)是使用者所能進行的單一中心工作。activity類負責視窗的建立和ui布局。必須調用setcontentview(view view)方法将ui放入activity中。是以可以将activity看做空的外部架構,然後填入你的ui。

現在看看例1-8中的tipster.java類片段。首先定義作為類的成員視窗部件。仔細研讀這一例子①到②的部分,作為以後的參考。

然後,用findviewbyid(int id)方法定位視窗部件。當在eclipse中清理并建構項目時,在main.xml檔案中定義的每個部件id自動在r.java檔案中定義。(如果将eclipse設定為自動建構,當更新main.xml時,r.java檔案立刻更新)。

每個視窗部件都從view類繼承而來,提供特殊的gui功能。textview類提供了在ui上放置标簽的手段,而edittext則提供了一個文本字段。檢視例1-8中③~⑥對應的部分,你可以看到如何使用findviewbyid()尋找視窗部件。

例1-8:/src/com/examples/tipcalc/tipster.java的代碼段2

解決易用性或者可用性問題

應用程式必須達到其他已經釋出的應用程式或者網頁的易用性水準。簡而言之,增加易用特性能夠帶來好的使用者體驗。為此,再次檢視例1-8。

關注使用view類的requestfocus()方法的地方④。因為edittext部件繼承自view類,該方法适用于它。是以,當應用程式加載時,總額(total amount)文本字段将得到焦點,光标出現在該控件中。這與流行web應用程式的螢幕登入相似——在登入螢幕中光标出現在使用者名文本字段中。

現在再看看calculate(計算)按鈕⑤,通過調用button部件上的setenabled(boolean enabled)将它禁用。這樣,使用者在輸入必要的字段值之前,使用者無法單擊它。如果在總額和人數字段未輸入值的情況下允許使用者單擊calculate按鈕,就必須編寫捕捉這些情況的驗證代碼,進而必須向使用者顯示有關空值的彈出式警告,這會增加不必要的代碼和使用者互動。當使用者看到calculate按鈕禁用時,就能很明顯地看出,除非輸入所有值,否則小費無法計算。

在例1-8中的⑦,這裡還禁用了other tip percentage(其他的小費比例)文本字段。這是因為應用程式加載時預設選中“15% tip”單選按鈕,這一預設選擇通過main.xml檔案完成。main.xml中用如下的語句選擇了“15% tip”單選按鈕:

radiogroup屬性android:checkedbutton允許選擇組中預設的一個radiobutton部件。

使用過流行桌面和web應用程式的大部分使用者都熟悉“disabled widgets enabled on certain conditions”(在某種條件下啟用已經禁用的部件)範例。增加這種小的便利功能總是能使應用更加易用,使用者體驗也更加豐富。

處理ui事件

和流行的windows、java swing、 flex和其他ui架構一樣,android也提供了事件模型,可以監聽ui中由使用者互動引起的事件。我們來看看如何在應用中使用android事件模型。

首先關注ui中的單選按鈕。我們希望知道,使用者選擇了哪一個單選按鈕,因為這能夠确定應用程式中的小費比例。使用靜态接口oncheckedchangelistener()“監聽”單選按鈕,當按鈕選擇狀态變化時将會得到通知。

在應用程式中,希望在選中other(其他)單選按鈕時才啟用other tip percentage文本字段。當“15% tip”和“20% tip”單選按鈕選中時,我們希望禁用文本字段。除此之外,還要添加一些有利于易用性的邏輯。之前已經讨論過,不應該在必要的所有字段中輸入有效值之前啟用calculate按鈕。對于這三個單選按鈕,應該確定在如下兩個條件下啟用calculate按鈕:

other單選按鈕選中,且other tip percentage文本字段輸入了有效值。

“15% tip”或“20% tip”單選按鈕選中,且total amount和no. of people文本字段輸入了有效值。

例1-9中對單選按鈕進行了處理。源代碼注釋已經做出了很好的解釋:

例1-9:/src/com/examples/tipcalc/tipster.java的代碼片段3

監控文本字段中的鍵盤活動

前面已經提到,除非文本字段輸入了有效值,否則calculate按鈕不能啟用。是以,必須確定calculate按鈕僅在total amount、no. of people和other tip percentage文本字段中輸入有效值之後啟用。other tip percentage文本字段僅在選中other tip percentage單選按鈕時啟用。

我們不必擔心輸入值的類型、使用者是否輸入負數或者字母,因為android:numeric屬性已經定義了文本字段,限制了使用者所能輸入的類型。隻需要確定輸入值存在。

使用靜态接口onkeylistener(),該接口在按下鍵時通知我們。通知在實際按鍵發送到edittext部件之前就會到達。

例1-10和例1-11處理文本字段中的按鍵事件。和例1-9中一樣,源代碼中的注釋也很好地解釋了代碼的功能。

例1-10:/src/com/examples/tipcalc/tipster.java的代碼片段4

注意,隻建立一個監聽器,而不是為每個文本字段都建立匿名/内部監聽器。我不确定自己的風格更好或者值得推薦,但是如果監聽器将要執行一些公用的操作,我就總以這種風格編寫代碼。所有文本字段都有公共的一個關注點:它們都不應該為空,隻有在它們有非空值時,才應該啟用calculate按鈕。

例1-11:代碼片段5,摘自keylistener.java

在例1-11的①處,檢查view類的id。記住,因為在main.xml檔案中的定義,每個視窗部件都有唯一的id。之後,在生成的r.java類中定義了這些值。

在②和③處,如果總金額或者人數字段中發生了鍵盤事件,将檢查字段中輸入的值,確定使用者對這兩個字段都沒有留白。

在④處,檢查使用者是否選擇other單選按鈕,然後确定other文本字段不為空。還要再次确定金額或者人數字段是否為空。

keylistener的目的現在很清晰了:確定所有文本字段非空,僅在這種情況下啟用calculate按鈕。

監聽按鈕單擊

現在來看calculate和reset(複位)按鈕。我們使用靜态接口onclicklistener()來通知使用者何時單擊這些按鈕。

和文本字段一樣,隻建立一個監聽器,在監聽器中檢測被單擊的按鈕。根據單擊的按鈕,調用calculate() 或reset()方法。

例1-12說明了為按鈕添加單擊事件監聽器的方法。

例1-12:/src/com/examples/tipcalc/tipster.java的代碼片段6

複位應用程式

當使用者單擊reset按鈕時,文本字段應該清除,選中預設的“15% tip”單選按鈕,應該清除所有計算結果。

例1-14展示了reset()方法。

例1-14:/src/com/examples/tipcalc/tipster.java的代碼片段8

驗證計算小費的輸入

前面已經提到,我們限制了文本字段中使用者所能輸入的值的類型。但是,使用者仍然可以在總金額、人數和其他小費比例字段中輸入0值,這會造成計算中除以0等錯誤。

如果使用者輸入0,必須顯示一個彈出式警告框,要求使用者輸入非0值。用showerroralert(string errormessage, final int fieldid)方法處理這一任務,稍後将對此進行更詳細的讨論。

首先,看看例1-15中展示的calculate()方法。注意使用者的值是如何解析為雙精度值的。

現在注意①和②中對0值的檢查。如果使用者輸入0,顯示一個彈出警告框對使用者加以警告。接下來看看③,因為使用者選擇了other單選按鈕,是以other tip percentage文本字段啟用,還必須檢查小費率是否為0。

當應用程式加載時,預設選中“15% tip”單選按鈕。如果使用者改變了選擇,将選中的單選按鈕id指派給成員變量radiocheckedid,正如在例1-9的oncheckedchangelistener中看到的那樣。

但是,如果使用者接受預設選擇,radiocheckedid将為預設值-1。簡而言之,我們永遠不會知道選中的是哪一個單選按鈕。當然,我們知道預設選中的是哪一個按鈕,可以編寫稍有不同的邏輯,如果radiocheckedid的值為-1就假定小費比例為15%。但是,如果查閱api,你就會發現:可以在radiogroup上而不是在單獨的單選按鈕上調用getcheckedradiobuttonid()方法。這是因為oncheckedchangelistener提供了選中的單選按鈕的id。

顯示結果

計算小費很簡單。如果沒有驗證錯誤,布爾标志iserror将為false。簡單的小費計算參見例1-15的④~⑤。接下來,計算出的值将在⑥~⑦中設定到textview視窗部件。

例1-15:/src/com/examples/tipcalc/tipster.java的代碼片段9

顯示警告

android提供alertdialog類來顯示彈出式警告。可以用它顯示一個具有多達3個按鈕和一條資訊的對話框。

例1-16展示的showerroralert方法使用alertdialog顯示錯誤消息。注意,向這個方法傳遞了兩個參數:string error message和int fieldid。第一個參數是我們希望向使用者顯示的錯誤消息。fieldid是導緻錯誤的字段id。在使用者關閉警告對話框之後,這個fieldid使我們能夠将焦點置于該字段之上,使用者由此得知該字段發生了錯誤。

例1-16:/src/com/examples/tipcalc/tipster.java的代碼片段10

組合以上各個功能,就實作了圖1-39中的效果。

《Android應用開發攻略》——1.15 程式:Android OS下的小費電腦Tipster

結語

android os的開發與其他ui工具包的開發(包括microsoft windows、 x windows、 java swing或adobe flex)沒有太大的不同。當然,android也有自己的特點,總體上是一個非常好的設計。xml布局範例相當好,可以用簡單的xml構造複雜的ui。此外,事件處理模型很簡單、具有豐富的特性,在代碼中使用也很直覺。

1.15.4 源代碼下載下傳url

可以從<code>http://www.vidyut.com/sunit/android/tipster.zip</code>下載下傳上述例子的源代碼。

1.15.5 二進制檔案下載下傳url

可以從<code>http://www.vidyut.com/sunit/android/tipster.zip</code>下載下傳上述例子的二進制檔案。