第 4 章
Android 應用程式設計
的基礎手藝:12 技
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
4.1 #1:如何建立 Menu 選單 4.2 #2:如何呈現按鈕(Button)之 1 4.3 #3:如何呈現按鈕(Button)之 2 4.4 #4:如何進行畫面佈局(Layout) 4.5 #5:如何呈現 List 選單之 1 4.6 #6:如何呈現 List 選單之 2
4.7 #7:如何運用相對性佈局(Relative Layout) 4.8 #8:如何運用表格式佈局(Table Layout) 4.9 #9:如何動態變換佈局
4.10 #10:如何定義自己的 View 4.11 #11:如何定義一組 RadioButton
4.12 #12:一個 Activity 啟動另一個 Activity
第 4 章 Android 應用程式設計的基礎手藝:12 技 83
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
從本章開始,將開始介紹及演練 Android 應用程式開發的基本 36 技了。
其中,有35 技是屬於 Android 框架之上的 Java 程式開發技巧。而第 36 技則屬 於Android 框架之下的 C 程式開發技巧。茲拿麥當勞的漢堡來做比喻,如下圖 所示:
芝麻:Android 應用程式(共 35 技)
上層麵包:Android 框架
牛肉和Cheese:框架與硬體之間 的 C 組件(第 36 技)
底層麵包:硬體組件
併不是 C 組件的技巧較少,而是本書範圍的緣故。本書的主角是「應用
程式開發」,所以偏重於芝麻部份的手藝。筆者的第二本書:「Android 應用
軟體架構設計」,也已經出版了,敬請閱讀之。
這裡以芝麻比喻應用程式,並不是說應用程式的渺小,而表示它的多與 香,若能與起司、牛肉互相搭配,更有特別風味。
在 本 章 裡 , 將 直 接 切 入 應 用 程 式 開 發 的 技 巧 。 如 果 你 還 沒 有 安 裝 過 Android SDK 及其 Eclipse 開發環境的話,請你先閱讀本書附錄-A,其內含:
◆ 如何安裝Android SDK 及其開發環境
◆ 如何著手撰寫Android 應用程式
◆ 如何執行Android 應用程式
如 果 你 覺 得 附 錄-A 還不夠詳細的話,請你上網tom-kao.blogspot.com或 www.misoo1.com 有更詳細的解說。現在就讓我們一起來演練 36 技吧!!
84 Android應用框架原理與程式設計36 技
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
4.1 #1:如何建立 Menu 選單?
我想大家都很熟悉 Menu 選單的用途了,本節就來說明如何定義 Android 的
Menu 選單,也演練其操作。
4.1.1 操作情境:
1. 此程式開始執行後,按下<MENU>就出現選單如下:
2. 如果選取<Add Item>選項,畫面標題(Title)區顯示出字串:”Insert…”。
3. 再按下<MENU>顯示出選單,如果選取<Del Item>選項,提標(Title)區顯示 出:”Delete…”。
4. 再按下<MENU>顯示出選單,如果選取<Exit>選項,程式就結束了。
4.1.2 撰寫步驟:
Step-1: 建立 Android 專案:ex01。
Step-2: 撰寫 Activity 的子類別:ex01,其程式碼如下:
// ---- ex01.java 程式碼 ---- package com.misoo.ex01;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class ex01 extends Activity {
public static final int ADD_ID = Menu.FIRST;
public static final int DELETE_ID = Menu.FIRST + 1;
第 4 章 Android 應用程式設計的基礎手藝:12 技 85
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public static final int EXIT_ID = Menu.FIRST + 2;
@Override public void onCreate(Bundle icicle) { super.onCreate(icicle);
setContentView(R.layout.main); }
@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu);
menu.add(0, ADD_ID, 0, R.string.menu_add);
menu.add(0, DELETE_ID, 1, R.string.menu_delete);
menu.add(0, EXIT_ID, 2, R.string.menu_exit);
return true; }
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) {
case ADD_ID: setTitle("Insert..."); break;
case DELETE_ID: setTitle("Delete..."); break;
case EXIT_ID: finish(); break;
}
return super.onOptionsItemSelected(item);
}}
Step-3: 修改/res/values/strings.xml 的內容,更改為:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ex01</string>
<string name="menu_add">Add Item</string>
<string name="menu_delete">Del Item</string>
<string name="menu_exit">Exit</string>
</resources>
並儲存之。
Step-4: 執行之。
4.1.3 說明:
1. 一開始,框架就反向呼叫 onCreate()函數,也呼叫 onCreateOptionsMenu()。
2. 當你選取<Add Item>選項時,框架會反向呼叫 onOptionsItemSelected()函數。
3. 框架是主角,ex01 類別只是被呼叫的配角,複雜的控制邏輯都為框架所做掉 了,所以程式碼便得簡單清晰了。
4. 呼叫 onCreate()函數時,此函數首先正向呼叫父類別 Activity 的 onCreate()函 數 , 先 執 行 父 類 別 的 預 設 行 為 , 然 後 才 執 行 ex01::onCreate()函數的附加行
86 Android應用框架原理與程式設計36 技
※ 因為框架的某個函數(不是 Activity::onCreate())呼叫 ex01::onCreate()函數時,
此onCreate()函數無法自己完成整個「create」的任務,而需要父類別的預設函 void paint() { onPaint(); }
Bird
第 4 章 Android 應用程式設計的基礎手藝:12 技 87
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
式碼就能明瞭了。
// IGraph.java ----介面 public interface IGraph { void onPaint();
public abstract class Shape implements IGraph{
Graphics m_gr;
public class Bird extends Shape { Graphics m_gr;
public Bird(Graphics gr) { super(gr);
m_gr = gr; } public void onPaint(){
super.onPaint();
// 畫圖(海鷗)指令
m_gr.setColor(Color.cyan);
m_gr.drawArc(30,80,90,110,40,100); m_gr.drawArc(88,93,90,100,40,80);
m_gr.setColor(Color.white);
m_gr.drawArc(30,55,90,150,35,75); m_gr.drawArc(90,80,90,90,40,80);
}}
//--- // JMain.java ---- 主程式
import java.awt.*;
import javax.swing.*;
class JP extends JPanel {
public void paintComponent(Graphics gr){
super.paintComponents(gr);
88 Android應用框架原理與程式設計36 技
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
IGraph cc = new Bird(gr); cc.paint();
}}
public class JMain extends JFrame {
public JMain(){ setTitle(""); setSize(350, 250); } public static void main(String[] args) {
JMain frm = new JMain();
JP panel = new JP();
frm.add(panel);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
}}
此程式畫出兩隻海鷗如下圖:
首先,主程式的指令:cc.paint()呼叫子類別 Bird 的 paint(),但是 Bird 並沒 有 paint()函數,於是採用父類別 Shape 的預設 paint()函數。此預設函數呼叫 onPaint(),就反向呼叫了子類別的 onPaint()。請注意,是父類別 paint()呼叫子類 別的 onPaint();並不是父類別 onPaint()來呼叫子類別的 onPaint()。反而是子類別 onPaint()呼叫父類別的 onPaint()。
4.1.5 補充說明(二):
※ 當你修改/res/values/strings.xml 內容之後,記得要存檔,為什麼呢?因為這樣 可以更新R.java 的內容,讓 menu.add(0, ADD_ID, R.string. menu_add)指令能找 到所要的字串。
※ 請你花一點時間認識一下R.java 的角色和特性,茲說明如下:
第 4 章 Android 應用程式設計的基礎手藝:12 技 89
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
---- 它(R.java)是連結*.java 的程式碼檔案和*.xml 佈局檔案的中介橋樑。
---- 在 res/layout/裡含有許*.xml 檔案。Eclipse 根據這些.xml 檔內容而自動產 生一個「R」類別(在/src/目錄區裡)。程式師不能用手工去更動它。
---- 當這些.xml 檔案有更新時,Eclipse 就會在你確認並將*.xml 存檔時,自動 更新它(即 R.java 檔案)的內容。
---- 它是程式裡可使用資源(/res/)的索引,對應到*.xml 檔案或字串。讓您的 AP 很方便透過它來取得相關的資源。也就是說,*.java 程式碼透過這索 引 就 能 方 便 地 取 得 所 需 要 的 資 源 。 例 如 , 在 setContentView (R.layout.main) 指 令 裡 的 R.layout.main 就 是 一 個 索 引 項 , 指 引 到 main.xml,就使用了 main.xml 所預設的(Default)陽春型畫面佈局了。