Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3496525
  • 博文数量: 864
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10634
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/zytc2009/BigTeam_learning

文章分类

全部博文(864)

文章存档

2023年(1)

2021年(1)

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(69)

2011年(103)

2010年(357)

2009年(283)

2008年(22)

分类: Java

2010-10-19 13:37:07

什麼是Intent(意圖)?

強大的事件處理「Intent」(意圖)是Android很強大的一種機制。

在 Android 應用程式框架中,有一個非常聰明的事件處理機制,稱之為「Intent」。Intent(意圖)的作用與事件(event)很像,但與傳統的事件處理仍然 有些差異。傳統的事件處理,講求的是「處理者(handler)的觸發」,當一事件發生時,便callback讓事件的處理者,或是直接將該事件轉送 (forward)給應用程式,由應用程式決定處理方式。

在「Intent」這樣的事件處理觀念裡,Android 試圖將事件解釋為「應用程式的意圖」或是「使用者的意圖」,並試著去解釋該意圖的目的,若 Android 系統本身能理解應用程式的意圖,便會「自行」去處理該意圖所應執行的工作。

Android的做法是,讓每個意圖(Intent)都帶有一個動作(action),並根據不同的動作去行動。

關於前述教學提到的Intent

在前面的教學裡,我們用到二次Intent如下:

1. 自行定義一個Intent、設定Service可接收此Intent,並透過「送出Intent給框架」的方式,請框架啟動該Service

2. 使用Android內部定義的動作「ACTION_VIEW」,來「檢視」(view)一個「URL」資料,當框架看到內部定義的ACTION_VIEW 動作時,便「自行」處理該Intent;處理的方式是啟動WebView並連上網站

以前述的教學為例,使用內建的動作“ACTION_VIEW”就可以很容易做出一個「啟動瀏覽器(WebView類別)上網」的應用程式。

透過這二個例子我們知道,Intent的動作可以是自行定義與框架內部定義二種。Android框架的Intent有很多方便實用的「內建動作」, 以下我們說明Android內建Intent的美麗之處。

Android內建的Intent Action

Android的框架確實是讓每個Intent都包含了一個動作,就稱為action。

為了讓大家更容易了解Intent的基本觀念,我們採用「體驗」的方式來說明如何使用內建的Action。現在,我們列舉以下三個情境,並分別實作 其範例:

HelloIntentDialer: 啟動撥號器(dialer)並撥號
HelloIntentMusic: 使用者按下「Select Music」後,可以由音樂清單裡選擇音樂並撥放
HelloIntentWallpaper: 啟動Android內建的「背景圖選擇器」,讓使用者更換背景

第二個範例”HelloIntentMusic”其實是ApiDemo裡的範例,而且是很容易能了解Intent內涵的好程式。

除了action外,Intent還可以包含另外一項資訊「data」。

Intent的action指定這個Intent的「動作」是什麼,框架會依指定的動作進行處理;有些action可以附帶一筆資料,這個資料是以 Uri的格式撰寫,在HelloIntentDialer的範例會再做說明。

內建的Intent有哪些呢?請參考Android Reference Guide中的Intent類別說明。上述三個範例分別使用以下三個action:

1. ACTION_CALL: 撥號
2. ACTION_GET_CONTENT: 啟動內容選取器
3. ACTION_SET_WALLPAPER: 設定Wallpaper

在進行範例講解前,可以先行閱讀Intent類別的說明。ACTION_CALL是一個內建的action,我們只要產生一個Intent物件,並 定義其「action」為ACTION_CALL即可通知框架「打電話」。

Android內建的action是相當實用的應用開發機制,同時也是Android OS最具代表性的機制之一。Android內建的Intent action分為二種:

1. Activity Action: 啟動Activity的action
2. Broadcast Action: 透過廣撥器處理的action

第一種action是activity action,用途是通知框架啟動Activity,這裡提出的三個範例,都是使用activity action。Broadcast action將在Broadcast的教學裡再做說明。

HelloIntentDialer是一個自動撥號程式,執行時會自動撥號到指定的 電話。這樣的程式要怎麼寫呢?先看到HelloIntentDialer.java的完整程式如下:

package com.moko.hellointentdialer;
 
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
 
public class HelloIntentDialer extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
 
Intent dial = new Intent();
dial.setAction("android.intent.action.CALL");
dial.setData(Uri.parse("tel:119"));
startActivity(dial);
}
}

因為permission的關係,所以也要在AndroidManifest.xml裡加上「CALL_PHONE」的權限。 AndroidManifest.xml的完整內容如下:


package="com.moko.hellointentdialer"
android:versionCode="1"
android:versionName="1.0">

android:label="@string/app_name">








>

這個範例相當簡單,但足以說明Intent的核心精神了。程式說明:

1. 先產生一個Intent物件:

 Intent dial = new Intent();

2. 設定Intent的action為「android.intent.action.CALL」,這是一個內建的action:

 dial.setAction("android.intent.action.CALL");

內建action「CALL」需要附帶一筆資料,而資料的寫法是使用URI格式:

 dial.setData(Uri.parse("tel:119"));

4. 「CALL」是一個activity action,所以呼叫startActivity()向Intent送給框架:

 startActivity(dial);

這個範例的概念並不難,「送出一個帶有內建action的Intent給框架,因為action為CALL,所以框架會去啟動撥號activity 並打電話。」

上一篇教學提到如何利用Intent實作「自動撥放」程式。而另外一個較具代表性的Intent應用就是「內容選擇器」。例如,要怎麼實作一個音樂 撥放機呢?先說明音樂撥放器HelloIntentSelect範例的使用情境如下:

1. 執行HelloIntentSelect後,出現一個「撥放音樂」的按鈕
2. 按下按鈕後,選擇一個音樂檔撥放

實作「選擇音樂檔」的做法是使用Intent的「chooser」觀念。程式做法如下:

1. 建立action為ACTION_GET_CONTENT的Intent:

 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

2.設定Intent的mime type,例如:設定Intent的mime type為聲音檔案:

 intent.setType("audio/*");

3.建立內容選擇器並送出Intent:

 startActivity(Intent.createChooser(intent, "Select music"));

以上的程式是根據Android的Reference Guide寫出來的。當Intent action為ACTION_GET_CONTENT時,表示要根據mime type來「取得內容」(get content),因此呼叫setType()方法,來定義內容的mime type。

定義好mime type後,再呼叫createChooser()方法來產生能取得此mime type內容的「選擇器」,簡單說,就是一個「檔案選取程式」。

利用Android的Intent觀念,我們以不到十行的程式碼實作了一個音樂撥放器。

Action的屬性寫法與常數寫法

Intent的action寫法有二種。第一種寫法是屬性(attribute)寫法,例如第一個HelloIntentDialer範例:

 dial.setAction("android.intent.action.CALL");

在「android.intent.action」套件(package)裡,定義了action的屬性。第二種寫法是常數寫法,例如第二個 HelloIntentSelect範例:

 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

在「Intent」類別(class)裡,定義了action的常數。在記憶的技巧上,可以用「xxx對於到ACTION_xxx」的方式記。例 如:

CALL(android.intent.action.CALL)就是ACTION_CALL(Intent.ACTION_CALL)。

又如,所以當我們講「GET_CONTENT」時,指的就是android.intent.action.GET_CONTENT;同理,講 ACTON_GET_CONTENT時,就是代表Intent.ACTION_GET_CONTNET。所以「GET_CONTENT」與 「ACTION_GET_CONTNET」代表相同的Intent。

hellointentselect-1.png
圖1: HelloIntentSelect主程式

hellointentselect-2.png
圖2: 出現一個Content Chooser:「音樂選擇器」

Android提供「SET_WALLPAPER」的內建Intent,當框架收到 這個Intent時,就會啟動「背景圖選擇器」,讓我們選取新的背景圖。送出SET_WALLPAPER intent的程式寫法如下:

        Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
startActivity(Intent.createChooser(intent, "Select Wallpaper"));

根據Reference Guide的說明,SET_WALLPAPER會啟動一個內容選擇器,所以同時地,我們先呼叫createChooser()方法建立一個內容選擇器後, 再送出Intent。

完整程式碼: HelloIntentWallpaper.java

package com.moko.hellointentwallaper;
 
import com.moko.hellointentwallaper.R;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
 
public class HelloIntentWallpaper extends Activity implements View.OnClickListener {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
 
Button button = (Button)findViewById(R.id.set_wallpaper);
button.setOnClickListener(this);
}
 
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
startActivity(Intent.createChooser(intent, "Select Wallpaper"));

}
}

UI設計: layout/main.xml


android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>

執行結果

hellointentwallpaper-1.png
圖1: HelloIntentWallpaper主程式

hellointentwallpaper-2.png
圖2: 「背景圖」選擇器


什麼是NinePatch圖檔

NinePatch是一種「可延展」的PNG圖檔。NinePatch圖檔的用途是製作「可隨文字大小縮放」的圖片,如圖1。

ninepatch-1.png
圖1: 文字背景可隨著文字大小縮放

NinePatch是很有用的圖片格式,可做為widget的「背景圖」。如圖1的範例,其應用程式的設計如下:

  • 文字部份使用TextView元件
  • 使用TextView的XML attribute來設定文字大小
  • 使用TextView的XML attribute來設定一張背景圖
  • 使用NinePatch圖片做為背景圖,如此一來背景圖就可以隨著文字大小縮放

首先,第一個工作就是「製作NinePatch圖檔」,方式如下。

Step 1. 準備一張原始的PNG圖檔,如圖2。

ninepatch-2.png
圖2: 原始PNG圖檔(arrow.png)

Step 2. 啟動Android提供的draw9patch工具,直接執行Android SDK tools/目錄下的draw9patch執行檔即可,如圖3。

ninepatch-3.png
圖3: Android SDK提供的draw9patch工具(點擊看原圖)

Step 3. 開啟原始PNG圖檔,編輯圖檔,如圖4。

ninepatch-4.png
圖4: 開始編輯圖檔(點擊看原圖)

如何編輯NinePatch圖檔

NinePatch圖檔的製作方式是「繪製二條線」,分別在原始圖檔的上方與左方繪出二條「黑線」,黑線所交集的區域即為「可延展」區域。如下圖的 粉紅色區域。

ninepatch-5.png
圖5: 定義延展區

「可延展區」是Android框架用來擺放文字的區域,換句話說,文字(TextView)只會被放置在粉紅色區域,並且擺放的原 則是「對準粉紅區域的中心點」,即上下置中、左右也置中。非「可延展區」,即綠色部份,並不會隨著文字的大小縮放延 展。所以:

1. 綠色區域是固定大小區域
2. 粉紅色區域是可延展區域、文字擺放於此

圖中的「二條黑線」是怎麼畫出來的呢?方式如下。

Step 4. 移動「Zoom」調整圖檔比例,讓「斑馬線」的大小能適中,如圖6。

ninepatch-6.png
圖6: 調整比例

Step 7: 畫黑線

斑馬線是用來畫黑線的區域,怎麼畫黑線呢?用滑鼠點斑馬線就可以了。要怎麼刪除黑線上?按住「Shift」再點斑馬線即可。斑馬線很不好點,所以如 果不是要特意訓練操作滑鼠的技巧以及考驗眼力,善用「Zoom」功能可以幫助黑線的繪製。

勾選「Show patches」選項,即可顯示粉紅色區域,如圖7。

ninepatch-7.png
圖7: 即時顯示可延展區

在draw9patch的右邊也會有縮放的展示圖。

Step 8: 完成NinePatch圖檔

儲存完成的NinePatch圖檔,draw9patch會自動將圖檔的副檔名儲存為*.9.png。完成NinePatch圖檔後,就可以開始寫 程式了。

* Update: 2009/9/20 - Android擺放文字於NinePatch圖檔上的原則「並非對準粉紅區域的中心點」,已刪除此句。

阅读(2124) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~