網頁

2010年12月8日 星期三

Android: 讀書心得 #2 基本選單與對話盒

接續上篇: 花栗鼠柑仔店: Android筆記: 讀書心得#1

參考資料: Amazon.com: Hello, Android: Introducing Google's Mobile Development Platform (Pragmatic Programmers) (9781934356562): Ed Burnette: Books

這段內容主要為:
第3章 使用者介面設計 基本選單與對話盒建立

第3章: 使用者介面設計 (Designing the User Interface)
1. 使用者介面可用程序方式(procedural)或宣告方式(declarative)來設計
(1) Procedural: 直接將UI的程式寫在code中, 類似Java Swing
(2) Declarative: 將UI的部分用宣告的方式表示, 類似HTML
Google較建議使用Declarative的方式來寫, 因為XML code比起Java code容易理解, 且日後修改也較為方便.


2. 一個最基本的Android程式
public class Sudoku extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    // Android 呼叫 onCreate() 方法來初始化 activity.
    super.onCreate(savedInstanceState);
    // 呼叫 setContentView() 將Android view widget填滿整個activity的畫面內容.
    setContentView(R.layout.main);
  }
}


3. R.layout.main是一個資源識別(resource identifier)對應到res/layout目錄中的main.xml檔案
main.xml用XML來宣告使用者介面, 只要修改了, Eclipse plug-in會解析且實例化定義在main.xml的資源, 設定到現有的activity. R class是自動被Eclipse plug-in所管理, 當你放上一個檔案在res目錄中, plug-in會注意到目錄的改變而將資源IDs加入到R.java(在gen目錄中).


4. layout是一個容器 (container) 用在將多個子物件放置在銀幕上 (在一個方形的父物件裡)


5. Android所提供較常見的layouts有: FrameLayout, LinearLayout, RelativeLayout, TableLayout
  • FrameLayout: 將其子物件由左上角開始排列, 適用在分頁顯示與影像切換 (tabbed views and image switchers.)
  • LinearLayout: 將其子物件排列成單一行或列,這是最常用的layout
  • RelativeLayout: 將其子物件依照相互的關係或對應到父物件來排列, 此方式較常用在表單(Form)的排列
  • TableLayout: 將其子物件以行列的方式排列, 與HTML的表格(Table)類似

6. @string/resid 語法會參照到 res/values/strings.xml 所定義的字串
在main.xml中, 一個簡單文字元件的定義, 其中@string/main_title會參照res/values/strings.xml
## /res/layout/main1.xml
...
<TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/main_title" />
...

## /res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">Sudoku</string>
  <string name="main_title">Android Sudoku</string>
  <string name="continue_label">Continue</string>
  <string name="new_game_label">New Game</string>
  <string name="about_label">About</string>
  <string name="exit_label">Exit</string>
</resources>


7. res/values/colors.xml: 顏色定義 (color definition)
## /res/values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <color name="background">#3500ffff</color>
</resources>

## /res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:background="@color/background"
  android:layout_height="fill_parent"
  android:layout_width="fill_parent"
  android:padding="30dip"
  android:orientation="horizontal" >
...


8. 銀幕上的介面元件與尺寸
  • px (pixels): 銀幕上的"點"(Dots)數.
  • in (inches): 用尺來量的實際大小.
  • mm (millimeters): 也是尺量出來的實際大小.
  • pt (points): 一英尺的1/72.
  • dp (density-independent pixels): 一個以銀幕的密度當基準的抽象單位, 假設銀幕上1英尺有160個點, 那1dp=1px
  • dip: dp的同義詞, Google的範例常用此名詞.
  • sp (scale-independent pixels): 與dp類似, 但額外增加的是可根據使用者設定的字型縮放.

9. @+id/resid: 建立一個新的資源ID供其他程式引用
## /res/layout/main.xml
...
<Button
  android:id="@+id/about_button"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/about_label" />
...

Android plugin會自動在R.class中產生:
    public static final class id {
        public static final int about_button=0x7f080003;
        public static final int about_content=0x7f080000;
        public static final int continue_button=0x7f080001;
        public static final int exit_button=0x7f080004;
        public static final int new_button=0x7f080002;
        public static final int settings=0x7f080005;
    }

在一般程式中要引用的話, 透過findViewById():
## /src/org/example/sudoku/Sudoku.java
View aboutButton = findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);


10. res/layout-land/main.xml: 橫式(landscape mode) layout 的定義檔
在Android模擬器按下"Ctrl_F11"可以將銀幕由直式變成橫式, Android會選用layout-land的main.xml作為銀幕顯示, 資源的字尾(suffixes)代表不同版本的資源, 不僅限於layout使用, 也可以用來指定不同的語系顯示. 可參考其他章節詳細說明.


11. 呼叫 findViewById() 尋找定義在R.java的資源ID所指到的View回傳給程式使用


12.  實作一個About說明視窗, 讓使用者可以點選, 可透過底下的方式達成
  • 定義一個新的 Activity 並啟動之
  • 使用AlertDialog類別, 並把它顯示出來
  • 使用android.app.Dialog類別, 並把它顯示出來
13.res/layout/about.xml: 定義一個新的About activity顯示程式資訊
書上這邊用的是12.說的第一個方法, 所以跟主要的Sudoku activity一樣, 先定義一個新的About activity出來
## res/layout/about.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:padding="10dip" >
  <TextView
    android:id="@+id/about_content"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/about_text" />
</ScrollView>

再來在 res/values/strings.xml 裡面增加對話盒中的文字內容,
## res/values/strings.xml
...
<string name="about_title">About Android Sudoku</string>
<string name="about_text">\
Sudoku is a logic-based number placement puzzle.
Starting with a partially completed 9x9 grid, the
objective is to fill the grid so that each
row, each column, and each of the 3x3 boxes
(also called <i>blocks</i>) contains the digits
1 to 9 exactly once.
</string>
...

strings.xml中可以放置簡單的HTML格式字串, 且假如有多行的話, 可以用"\"來表示"接續行"避免顯示多一行空白.


14. 再來產生一個新的About.java檔
裡面有最基本的onCreate()與setContentView()即可

15. 回到Sudoko.java, 要來銜接About.java
透過setOnClickListener()來設定告知Android當使用者觸碰或按下View時要做的事情

## src/org/example/sudoku/Sudoku.java
View aboutButton = findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);

16. 補上OnClickListener的程式碼
## src/org/example/sudoku/Sudoku.java
public class Sudoku extends Activity implements OnClickListener {
  // ...
  public void onClick(View v) {
    switch (v.getId()) {
      case R.id.about_button:
      Intent i = new Intent(this, About.class);
      startActivity(i);
    break;
    // More buttons go here (if any) ...
    }
  }
}

要啟動一個Activity, 首先要先用一個Intent(Intent | Android Developers)的abstract class.

[Note]
An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.

除此之外要注意的是, 任何在Android中要啟動的Activity都需要在AndroidManifest.xml中宣告, 否則會有錯誤訊息, 定義如下:

<activity android:name=".About"
  android:label="@string/about_title" >
</activity>

把上面那段加入AndroidManifest.xml中,
最後執行結果如下:



(第3章 使用者介面設計 未完待續)

沒有留言:

張貼留言