Android 資源(resource)學習小結
Android 資源(resource)學習小結
運用Android SDK進行UI開發時,雖然也可以使用純程式碼來完成,但是那種方法對我這種剛學習Android對API還不懂的人來說,能進行類似VB、MFC一樣圖形化開發自然是最合適不過的。幸好Android也提供了這種方式,在Android工程檔案中專門有個res目錄用於存放資源,該目錄下的資源可以進行視覺化的編輯,編寫好的資源通過AAPT(Android AssetPackaging Tool)工具自動生成gen目錄下的R.java資源索引檔案,之後在Java程式碼和XML資原始檔中就可以利用索引來呼叫資源了。
Android提供瞭如此便利的資源架構,要想使用它,還是要對他有深入的瞭解才可以,以下就這陣子對Android資源的學習進行小結來回顧和整理幾個問題
Android資源目錄結構問題?
Android資源支援哪些型別資源,他們具體的語法和使用規則?
Android資源目錄結構
Android資源除了assets目錄是與res同級外,其它資源均被放在res/目錄下面,該目錄下面的資原始檔夾並不是隨意命名的,需要遵循嚴格的規範,否則編譯生成R.java過程中會報類似“invalidresource directory name **”的錯誤提示,並且導致R.java自動生成失敗。
常用的預設目錄和對應資源型別在SDK幫助中有表格列出,簡單摘抄如下
目錄Directory |
資源型別Resource Types |
res/animator |
存放定義了property animations(android 3.0新定義的動畫框架)的XML檔案 |
res/anim/ |
存放定義了補間動畫(tweened animation)或逐幀動畫(frame by frame animation)的XML檔案。(該目錄下也可以存放定義property animations的XML檔案,但是最好還是分開存放) |
res/raw/ |
存放直接複製到裝置中的任意檔案。它們無需編譯,新增到你的應用程式編譯產生的壓縮檔案中。要使用這些資源,可以呼叫Resources.openRawResource(),引數是資源的ID,即R.raw.somefilename |
res/drawable/ |
存放能轉換為繪製資源(Drawable Resource)的點陣圖檔案(字尾為.png, .9.png, .jpg, .gif的影象檔案)或者定義了繪製資源的XML檔案 |
res/color/ |
存放定義了顏色狀態列表資源(Color State List Resource)的XML檔案 |
res/layout/ |
存放定義了使用者介面佈局的XML檔案 |
res/menu/ |
存放定義了應用程式選單資源的XML檔案 |
res/values/ |
存放定義了多種型別資源的XML檔案 這些資源的型別可以是字串,資料,顏色、尺寸、樣式等等,具體在後面詳述 |
res/xml/ |
存放任意的XML檔案,在執行時可以通過呼叫Resources.getXML()讀取 |
上面說過res資料夾下的資料夾命名是有規矩的,否則會報類似“invalidresource directory name **”的錯誤提示,除了上表提供的預設資料夾,一般可以用預設資料夾名加短橫線加配置相關的限定符構成需要的資原始檔夾,用於區別不同螢幕解析度、不同機型特點(是否帶鍵盤等)以及不同的本地化資源等用處,詳細參考API說明文件。具體案例如下圖所示
其中的values-zh-rCN就是中文簡體資源包,用於本地化,至於其它就對照API說明文件來分析。一般專案預設的資原始檔夾名稱就夠了。
由上面資源表可知,每個資料夾中存放的檔案型別不僅有規定,而且對檔案內容也是有嚴格要求的,曾經將一個定義佈局的spinner.xml檔案放置在res/values,結果就報“Invalid start tag *Layout spinner.xml”錯誤,並導致R.java沒有生成;將該佈局檔案放置在res/color下面,雖然沒有報錯,但是原本的佈局檔案,不再是正確生成為形如“R.layout.spinner”的佈局資源,而是生成為了“R.color.spinner”的顏色資源索引,具體如下所示
佈局檔案放置正確的R.java中程式碼
public static final class layout {
public static final int autocomplete=0x7f030000;
public static final int spinner=0x7f03000d;
}
佈局檔案放置錯誤的R.java中程式碼
public static final class color {
public static final int solid_blue=0x7f050001;
public static final int spinner=0x7f050004;
}
另外當一種資源定義XML檔案放在不對應的res資料夾下,在視覺化環境下,也就不能正確顯示和編輯。
通過上述一些特性,我們可以猜測出android的aapt工具的工作原理,先是根據資料夾名來進行對資原始檔和XML檔案進行不同的解析和編譯規則進行解析和編譯,ADT工具也是根據具體資料夾名稱呼叫不同的規則來視覺化編輯和呈現。
由於Android資原始檔和資料夾有那麼多的規矩,所以新手還是建議用eclipseIDE提供的建立XML檔案的框架來建立資原始檔和資原始檔夾即在你需要建立資原始檔時,通過“File”“New”“Android XML file”就可以彈出如下的New Android XML File對話方塊,
選好工程,填好資原始檔名,在“What type of resourcewould you like to create”中勾選需要建立的資源型別,假如是非預設目錄資源就在“what type of resource configuration would you like?”新增需要的配置型別,就可以在“Folder”中自動生成資源xml所在的資料夾,這個不用修改它。其它就根據需要來選擇,然後點選“Finish”,就可以創建出符合規則的資原始檔了。在這裡需要注意的是資原始檔名不能使用大寫字母。
是不是很省事,又能做出正確的事情啊,呵呵!
Android資源型別及其簡單使用
上面對Android的資源目錄的分析中,已經大致展現了Android資源型別的大致脈絡,下面從簡單資源先入手詳細羅列下具體的資源型別和使用。一般而言,沒有明說資源不能在XML資原始檔中呼叫,那麼該資源都是既可以在其它XML資原始檔中呼叫又可以在Java程式碼中呼叫的。
字串資源位於/res/values目錄下,一般定義為/res/values/strings.xml檔案中(檔名隨意,但是目錄是固定的),主要定義的是應用程式需要用到的字串資源,這和Symbian的字串資源規劃類似,不過更加進步了些。當然,你非要在程式碼中使用字串也可以,但那種方式並不是推薦的。字串資源有String、String Array和Quantity Strings (Plurals)三類,其各自語法和用例稍微有些區別
<?xml version="1.0"encoding="utf-8"?>
<resources>
<string name="string_name">text_string</string>
</resources>
上面的string_name字串資源,可以通過如下兩種方法呼叫
XML資源定義中
@[package:]string/string_name
Java程式碼中
R.string.string_name
假設有個資原始檔為res/values/strings.xml,其內容如下:
<?xml version="1.0"encoding="utf-8"?>
<resources>
<string name="hello">Hello!</string>
</resources>
那麼這個hello字串資源在其它XML資原始檔中的呼叫如下所示
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
在java程式碼中的呼叫如下
String string = getString(R.string.hello);
<?xml version="1.0"encoding="utf-8"?>
<resources>
<string-array name="string_array_name">
<item>text_string</item>
</string-array>
</resources>
上面的string_array_name字串資源,可以通過如下兩種方法呼叫
XML資源定義中
@[package:]array/string_array_name
Java程式碼中
R.array.string_array_name
假設有個String Array資源在/res/values/stringArray.xml中,內容如下
<?xml version="1.0"encoding="utf-8"?>
<resources>
<string-array name="planets_array">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
</string-array>
</resources>
那麼在其它資源XML檔案中,假設有個下拉列表需要用到上面的字串陣列資源,則可以如下呼叫
<Spinnerandroid:id="@+id/spinner1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:entries="@array/planets_array">
</Spinner>
在Java程式碼中的呼叫示例如下
Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);
<?xml version="1.0"encoding="utf-8"?>
<resources>
<plurals name="plural_name">
<item quantity=["zero" | "one" | "two"| "few" | "many" |"other"]>text_string</item>
</plurals>
</resources>
幫助文件中沒有給出XML資原始檔中對其的使用方法,也沒有明確說不能通過XML呼叫,我也沒有搞明白這個資源,所以暫時只給出Java程式碼中對上述plural_name資源的呼叫情況
R.plurals.plural_name
其中關於zero、one、two、few和many在幫助文件中有詳細的釋義,這裡就不單獨羅列。
假設有個Quantity Strings資源定義在/res/values/stringQuantity.xml中,內容如下
<?xml version="1.0"encoding="utf-8"?><resources>
<plurals name="numberOfSongsAvailable">
<item quantity="one">One song found.</item>
<item quantity="other">%d songs found.</item>
</plurals>
</resources>
由於這個資源,我還不太會用,所以只好照抄幫助文件的使用,至於XML文件中如何使用還不會,在Java程式碼中使用如下所示
int count = getNumberOfsongsAvailable();
Resources res = getResources();
String songsFound = res.getQuantityString(R.plurals.numberOfSongsAvailable, count, count);
Android字串定義時,假如有特殊字元,而沒有用到轉義字元,就必須用雙引號將字串完全包住,具體如下所示
//正確使用方法
<stringname="good_example">"This'll work"</string>
<stringname="good_example_2">This\'ll also work</string>
//錯誤
<stringname="bad_example">This won't work!</string>
//錯誤不可使用html轉義字元
<stringname="bad_example_2">This won't work!</string>
由上可知,雖然字串支援HTML標記,但是不支援html的轉義字元。另外對於帶格式/風格的字串資源,也是不能在XML程式碼中呼叫,只能在Java程式碼中使用,而且使用過程中有點複雜,需要用htmlEncode解析,然後用String.format()來實現賦值,接著用fromHtml(String)得到格式化後的string。具體幫助文件給出的用例如下
XML資源定義如下:
<resources>
<string name="welcome_messages">Hello, %1$s! You have<b>%2$d new messages</b>.</string>
</resources>
Java程式碼呼叫如下:
String escapedUsername = TextUtil.htmlEncode(username);
Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), escapedUsername,mailCount);
CharSequence styledText = Html.fromHtml(text);
整數常量在C/C++通常是放在程式碼裡面,android將整型常量、Bool常量和陣列常量等等都可以放到XML資原始檔中,後面具體介紹這些資源時就不再做展開了。一般整數常量被放置在/res/values/integers.xml中,同樣檔名可以隨意,但是目錄必須固定在/res/values/下
<?xml version="1.0"encoding="utf-8"?>
<resources>
<integer name="integer_name">integer</integer>
</resources>
上面的integer_name整數常量,可以通過如下兩種方法呼叫
XML資源定義中
@[package:]integer/integer_name
Java程式碼中
R.integer.integer_name
假設整數常量放置在/res/values/integers.xml中,內容如下
<?xml version="1.0"encoding="utf-8"?>
<resources>
<integer name="max_speed">75</integer>
<integer name="min_speed">5</integer>
</resources>
我們在程式碼中使用的時候,通過以下方式進行呼叫
Resources res = getResources();
int maxSpeed = res.getInteger(R.integer.max_speed);
<?xml version="1.0"encoding="utf-8"?>
<resources>
<integer-array name="integer_array_name">
<item>integer</item>
</integer-array>
</resources>
上面定義的integer_array_name可以用如下兩種方法呼叫
XML資源定義中
@[package:]array.integer_array_name
Java程式碼中
R.array.integer_array_name
假設整數陣列放置在/res/values/intergers.xml中,內容如下所示
<?xml version="1.0"encoding="utf-8"?>
<resources>
<integer-array name="bits">
<item>4</item>
<item>8</item>
<item>16</item>
<item>32</item>
</integer-array>
</resources>
該資源在java程式碼中的呼叫為
Resources res = getResources();
int[] bits =res.getIntArray(R.array.bits);
Typed Array資源有點類似於Symbian中瘦模板類的,用於存放多種不同型別資源陣列的資源,本來想將這個資源放後面講解,但是前面提供了一系列陣列案例,就一併將這個陣列也提前羅列下吧。該資源一般放置於/res/values/arrays.xml中
<?xml version="1.0"encoding="utf-8"?>
<resources>
<array name="typed_array_name">
<item>resource</item>
</array>
</resources>
上面的typed_array_name資源,可以通過如下兩種方法呼叫
XML資源定義中
@[package:]array/typed_array_name
Java程式碼中
R.array.array_name
假設有兩個Typed Array資源定義在/res/values/arrays.xml中,具體如下
<?xml version="1.0"encoding="utf-8"?>
<resources>
<array name="icons">
<item>@drawable/home</item>
<item>@drawable/settings</item>
<item>@drawable/logout</item>
</array>
<array name="colors">
<item>#FFFF0000</item>
<item>#FF00FF00</item>
<item>#FF0000FF</item>
</array>
</resources>
該資源通過以下方法在java程式碼中呼叫
Resources res = getResources();
TypedArray icons = res.obtainTypedArray(R.array.icons);
Drawable drawable = icons.getDrawable(0);
TypedArray colors = res.obtainTypedArray(R.array.icons);
int color = colors.getColor(0,0);
由於每一種型別都是通過不同的API來獲取陣列中的元素,比如上面用例裡面color用int getColor(int index, intdefValue)函式,Drawable用Drawable getDrawable(int index)函式,至於其它相關的型別該呼叫什麼函式來獲取具體可以參看android.content.res.TypedArray的原始碼檔案\frameworks\base\core\java\android\content\res\TypedArray.java來獲得更多的詳情。
該資源一般定義在/res/values/bools.xml中。
<?xml version="1.0"encoding="utf-8"?>
<resources>
<bool name="bool_name">[true| false]</bool>
</resources>
上面的bool_name布林常量資源,可以通過如下兩種方法呼叫
XML資源定義中
@[package:]bool/bool_name
Java程式碼中
R.bool.bool_name
假設有bool常量資源定義在res/values/bools.xml中,內容如下
<?xml version="1.0"encoding="utf-8"?>
<resources>
<bool name="screen_small">true</bool>
<bool name="adjust_view_bounds">true</bool>
</resources>
那麼在xml資源中的呼叫可以如下
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="@drawable/logo"
android:adjustViewBounds="@bool/adjust_view_bounds"/>
在Java程式碼中的呼叫如下
Resources res = getResources();
boolean screenIsSmall = res.getBoolean(R.bool.screen_small);
該資源定義跟螢幕顯示相關的一些尺寸常量,一般儲存在/res/values/dimen.xml檔案中
具體的度量單位有:
px(象素): 螢幕實際的象素,常說的解析度1024*768pixels,就是橫向1024px, 縱向768px,不同裝置顯示效果相同。
in(英寸): 螢幕的物理尺寸, 每英寸等於2.54釐米。
mm(毫米): 螢幕的物理尺寸。
pt(點): 螢幕的物理尺寸。1/72英寸。
dp/dip: 與密度無關的象素,一種基於螢幕密度的抽象單位。在每英寸160點的顯示器上,1dp =1px。但dp和px的比例會隨著螢幕密度的變化而改變,不同裝置有不同的顯示效果。
sp: 與刻度無關的象素,主要用於字型顯示best for textsize,作為和文字相關大小單位。
<?xml version="1.0"encoding="utf-8"?>
<resources>
<dimen name="dimension_name">dimension</dimen>
</resources>
假設定義了一個dimen資源在res/values/dimens.xml檔案中
<?xml version="1.0"encoding="utf-8"?>
<resources>
<dimen name="textview_height">25dp</dimen>
<dimen name="textview_width">150dp</dimen>
<dimen name="ball_radius">30dp</dimen>
<dimen name="font_size">16sp</dimen>
</resources>
我們可以在XML資源中進行如下呼叫
<TextView
android:layout_height="@dimen/textview_height"
android:layout_width="@dimen/textview_width"
android:textSize="@dimen/font_size"/>
在Java程式碼中進行如下呼叫
Resources res = getResources();
float fontSize = res.getDimension(R.dimen.font_size);
顏色常量通常被定義在/res/values/colors.xml檔案內,同時顏色資源作為一種可繪製的資源,也可以被定義在/res/drawable/資料夾下,呼叫方式也完全不同,在這裡只介紹作為常量的顏色資源。雖然兩種定義和呼叫方式不同,但是顏色的數值表現形式卻是一樣的,都是形如下面的十六進位制格式(後面涉及顏色數值就不再贅述了)
#RGB
#ARGB
#RRGGBB
#AARRGGBB
比如#f00表示不透明的12位紅色,而#80ff0000表示透明的32位真彩紅色
<?xml version="1.0"encoding="utf-8"?>
<resources>
<color name="color_name">hex_color</color>
</resources>
上面的color_name顏色常量可以通過如下兩種方法呼叫
XML資源定義中
@[package:]color/color_name
Java程式碼中
R.color.color_name
假設有顏色常量被定義在res/values/colors.xml中
<?xml version="1.0"encoding="utf-8"?>
<resources>
<color name="opaque_red">#f00</color>
<color name="translucent_red">#80ff0000</color>
</resources>
在XML要使用該常量資源,可以通過如下方法
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@color/translucent_red"
android:text="Hello"/>
在Java程式碼中如果想使用該資源,則如下呼叫
Resources res = getResources();
int color = res.getColor(R.color.opaque_red);
至此我們將res/values下面定義的資源型別除了風格(Style)和主題(Theme)資源外,全部都介紹過了,由於風格和主題案例需要設計佈局(layout)和View等,所以最後再涉及這兩類資源的介紹。
該資源被放置於/res/color/目錄下面,用來定義一個類似Button控制元件在不同狀態下需要呈現不同的顏色。因此這種XML資原始檔描述的是跟控制元件狀態相掛鉤的顏色狀態,具體見下面語法
假如有個狀態顏色列表資原始檔res/color/colorstatefile.xml
<?xml version="1.0"encoding="utf-8"?>
<selectorxmlns:android="http://schemas.android.com/apk/res/android" >
<item android:color="hex_color"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"]/>
</selector>
該選單資源可以通過如下渠道訪問
XML資源定義中
@[package:]color/ colorstatefile
Java程式碼中
R.color. colorstatefile
有一個定義了button狀態顏色列表的資源res/color/button_text.xml
<?xml version="1.0"encoding="utf-8"?>
<selectorxmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"android:color="#ffff0000"/> <!-- pressed -->
<item android:state_focused="true"android:color="#ff0000ff"/> <!-- focused -->
<item android:color="#ff000000"/> <!-- default -->
</selector>
則在佈局檔案中一個Button控制元件需要使用該狀態顏色,就可以通過如下呼叫
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button_text"
android:textColor="@color/button_text"/>
佈局資源是放置於/res/layout/下面的用於定義UI介面的XML檔案,該資源被用於Activity或者其他UI元件。由於我在學習android之前,沒有過Java GUI開發的經驗,所以不清楚Java裡面的UI設計思想,只知道Android UI類都是基於View和ViewGroup兩個類,View類的子類就是“widget”即類似文字框、編輯框等UI控制元件,ViewGroup的子類就是“Layout”即LinearLayout、RelativeLayout等佈局容器類。佈局容器類裡面可以佈局UI控制元件和其它佈局容器物件。具體結構如下所示
這和Symbian裡面控制元件和檢視概念有些區別,Symbian裡面所有的UI類都是派生自CCoeControl,即一個控制元件可以成為另一個控制元件的容器。在Android中容器就是容器,控制元件就是控制元件,只不過容器中除了能放置控制元件外,也能放置容器,這為我們建立自有複雜的介面提供了條件。
Android提供了多種佈局型別,列表如下
佈局型別 |
佈局標籤 |
說明 |
線性佈局 |
LinearLayout |
按照垂直或水平方向佈置控制元件,每行或列只能放置一個控制元件 |
幀佈局 |
FrameLayout |
從螢幕左上角佈置控制元件,不能控制位置,多個控制元件會疊加放置 |
相對佈局 |
RelativeLayout |
佈局內的view元件元素按照依賴關係相對位置來放置,位置計算只執行一次,因此必須按依賴反向安排元件順序 |
絕對佈局 |
AbsoluteLayout |
按照絕對座標(即x,y)來佈局控制元件(相對用的不多) |
表格佈局 |
TableLayout |
按照行列方式佈局控制元件,類似於HTML裡的Table |
切換卡 |
TabWidget |
實現標籤切換的功能,是一個派生自LinearLayout的佈局方式 |
<?xml version="1.0"encoding="utf-8"?>
<ViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@[+][package:]id/resource_name"
android:layout_height=["dimension" | "fill_parent" |"wrap_content"]
android:layout_width=["dimension" | "fill_parent" |"wrap_content"]
[ViewGroup-specific attributes] >
<View android:id="@[+][package:]id/resource_name"
android:layout_height=["dimension" | "fill_parent" |"wrap_content"]
android:layout_width=["dimension" | "fill_parent" |"wrap_content"]
[View-specific attributes] >
<requestFocus/>
</View>
<ViewGroup >
<View />
</ViewGroup>
<include layout="@layout/layout_resource"/>
</ViewGroup>
上面的佈局資原始檔名為layoutEx.xml,則可以通過如下兩種方法呼叫
在XML資源定義中
@[package:]layout/layoutEx
Java程式碼中
R.layout.layoutEx
為了儘可能在在一個例子裡面體現更多的佈局,為此用例使用如下五個佈局檔案來關聯一個Activity
第一個佈局檔案為簡單的相對佈局,其檔名為right.xml,內容如下
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayoutandroid:id="@+id/right"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
>
<TextViewandroid:id="@+id/right_view1"
android:background="@drawable/yellow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="第二組第1項" />
<TextViewandroid:id="@+id/right_view2"
android:background="@drawable/blue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/right_view1"
android:text="第二組第二項" />
</RelativeLayout>
第二個佈局檔案為水平線性佈局內嵌入兩個佈局檔案,檔名為first.xml,內容如下
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:id="@+id/left_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dip"
android:layout_height="100dip"
android:padding="10dip" >
<TextViewandroid:id="@+id/Left_view1"
android:background="@drawable/blue"
android:layout_width="fill_parent"
android:layout_height="50px"
android:text="第1組第1項" />
<TextViewandroid:id="@+id/Left_view2"
android:background="@drawable/yellow"
android:layout_width="fill_parent"
android:layout_height="50px"
android:layout_below="@id/Left_view1"
android:text="第1組第2項" />
</RelativeLayout>
<include layout = "@layout/right" />
</LinearLayout>
第三個佈局檔案為表格佈局檔案,檔名為table.xml,內容如下
<TableLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"android:layout_height="wrap_content"
android:clickable="true"android:stretchColumns="1">
<TableRow>
<TextViewandroid:text="使用者名稱:" android:textStyle="bold"
android:gravity="right"android:padding="3dip" />
<EditTextandroid:id="@+id/username" android:padding="3dip"
android:scrollHorizontally="true"/>
</TableRow>
<TableRow>
<TextViewandroid:text="登入密碼:" android:textStyle="bold"
android:gravity="right"android:padding="3dip" />
<EditTextandroid:id="@+id/password" android:password="true"
android:padding="3dip"android:scrollHorizontally="true" />
</TableRow>
<TableRowandroid:gravity="right">
<Buttonandroid:id="@+id/cancel"
android:text="取消" />
<Buttonandroid:id="@+id/login"
android:text="登入" />
</TableRow>
</TableLayout>
第四個佈局檔案為幀佈局,檔名為frame.xml,內容如下
<?xml version="1.0"encoding="utf-8"?>
<FrameLayoutandroid:id="@+id/left"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageViewandroid:id="@+id/photo" android:src="@drawable/bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
第五個佈局檔案為垂直線性佈局檔案,檔名為main.xml,內容如下
<?xml version="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout = "@layout/first" />
<include layout = "@layout/table" />
<include layout = "@layout/frame" />
</LinearLayout>
最後在主Activity中的
public class ActivityMain extends Activity{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
結果程式執行後,顯示如下圖所示的結果
選單資源位於/res/menu/目錄下,相較於其它資源而言,選單在android中目前我看到的程式碼,很多時候是用程式碼直接生成的,直接用資源的比較少一點。在Android中,有三類選單:選項選單、上下文選單和子選單。從建立選單的步驟來看,選項選單和子選單的建立都遵循下列步驟:
a、覆蓋Activity的OnCreateOptionsMenu(Menu menu)方法,在其中新增彈出選單的程式碼
b、覆蓋Activity的OnOptionsItemSelected()方法,在其中新增選中不同選單項後的處理流程
如果是通過資源來建立選單,那麼兩者程式碼沒有區別,只是資源編輯考慮了樹形結構而已,假如程式碼建立,那麼前者使用Menu的add方法,後者通過SubMenu的Add方法。
上下文選單的建立步驟為:
a、覆蓋Activity的OnCreateContextMenu()方法,在其中新增彈出選單的程式碼
b、覆蓋Activity的OnContextItemSelected()方法,在其中新增選中不同選單項後的處理流程
c、一般在Activity的OnCreate函式中呼叫registerForContextMenu()方法,為檢視註冊上下文選單
假如有個選單資原始檔res/menu/menufile.xml
<?xml version="1.0"encoding="utf-8"?>
<menuxmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@[+][package:]id/resource_name"
android:title="string"
android:titleCondensed="string"
android:icon="@[package:]drawable/drawable_resource_name"
android:onClick="method name"
android:showAsAction=["ifRoom" | "never" |"withText" | "always"]
android:actionLayout="@[package:]layout/layout_resource_name"
android:actionViewClass="class name"
android:alphabeticShortcut="string"
android:numericShortcut="string"
android:checkable=["true" | "false"]
android:visible=["true" | "false"]
android:enabled=["true" | "false"]
android:menuCategory=["container" | "system" |"secondary" | "alternative"]
android:orderInCategory="integer" />
<group android:id="@[+][package:]id/resource name"
android:checkableBehavior=["none" | "all" |"single"]
android:visible=["true" | "false"]
android:enabled=["true" |"false"]
android:menuCategory=["container" | "system" |"secondary" | "alternative"]
android:orderInCategory="integer" >
<item />
</group>
<item >
<menu>
<item />
</menu>
</item>
</menu>
該選單資源可以通過如下渠道訪問
XML資源定義中
@[package:]menu/menufile
Java程式碼中
R.menu.menufile
由上述語法結構,可知<menu>根元素,在<menu>根元素裡面會巢狀<item>和<group>子元素,<item>元素中也可巢狀<menu>形成子選單。
下面對語法中的標籤做下簡單分析
<menu>標籤是根元素,他沒有屬性,可包含<item>和<group>子元素。
<group>標籤表示一個選單組,相同的選單組可以一起設定其屬性,例如visible、enabled和checkable等屬性。具體羅列說明如下:
id:唯一標示該選單組的引用id
menuCategory:對選單進行分類,定義選單的優先順序,有效值為container、system、secondary和alternative
orderInCategory:一個分類排序整數
checkableBehavior:選擇行為,單選、多選還是其他。有效值為none、all和single
visible:是否可見,true或者false
enabled:是否可用,true或者false
<item>標籤表示具體的選單項,包含在<menu>或<group>中。<item>元素的屬性說明如下:
id:唯一標示選單的ID引用,選中該選單項後,MenuItem::getItemId()返回的就是這個ID值
menuCategory:選單分類
orderInCategory:分類排序
title:選單標題字串
titleCondensed:濃縮標題,適合標題太長的時候使用
icon:選單的圖示
alphabeticShortcut:字元快捷鍵
numericShortcut:數字快捷鍵
checkable:是否可選
checked:是否已經被選
visible:是否可見
enabled:是否可用
這裡用例分別為兩個TextView彈出兩個上下文選單,所以使用了兩個menu資源,具體例項如下。
示例程式的佈局res/layout/main.xml,內容為
<?xml version="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="File Menu" />
<TextView
android:id="@+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="EditMenu" ></TextView>
</LinearLayout>
兩份選單資源分別為
//res/menu/view1menu.xml
<?xml version="1.0"encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="File">
<item
android:id="@+id/newFile"
android:title="New"
android:alphabeticShortcut="n"/>
<item
android:id="@+id/openFile"
android:title="Open"
android:alphabeticShortcut="o"/>
<item
android:id="@+id/saveFile"
android:title="Save"
android:alphabeticShortcut="s"/>
</menu>
//res/menu/view2menu.xml
<?xml version="1.0"encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/cut"
android:title="Cut" />
<item
android:id="@+id/copy"
android:title="Copy"/>
<item
android:id="@+id/past"
android:title="Past"/>
</menu>
程式在Activity中的程式碼清單如下
public class MenuDemoActivity extendsActivity
{
private TextView view1;
private TextView view2;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view1 = (TextView) findViewById(R.id.textView1);
view2 = (TextView) findViewById(R.id.textView2);
registerForContextMenu(view1);
registerForContextMenu(view2);
}
@Override
public void onCreateContextMenu(ContextMenumenu, View v, ContextMenu.ContextMenuInfo menuInfo)
{
MenuInflater inflater =getMenuInflater();
switch(v.getId())
{
case R.id.textView1:
menu.setHeaderTitle("File");
inflater.inflate(R.menu.view1menu,menu);
break;
case R.id.textView2:
inflater.inflate(R.menu.view2menu,menu);
menu.setHeaderTitle("Edit");
break;
}
}
@Override
public boolean onContextItemSelected(MenuItemitem)
{
super.onContextItemSelected(item);
switch(item.getItemId())
{
case R.id.newFile:
break;
}
return false;
}
}
Android 3.0 SDK釋出後,動畫提供了三種實現方案:
逐幀動畫型別(frame by frame Animation),這種動畫的效果跟電影和gif動畫一樣的原理一樣,即用一幀一幀的圖片設定顯示時間和順序,進行順序播放,呼叫資源的相關原始碼位於\frameworks\base\graphics\java\android\graphics\drawable\AnimationDrawable.java中,自然具體類就是android.graphics.drawable.animationdrawable;
補間動畫(Tween Animation),這種動畫是針對view控制元件進行移動、縮放、旋轉和Alpha漸變等操作來實現動畫效果。呼叫資源的相關原始碼不像逐幀動畫那麼簡單,具體有個原始碼包位於\frameworks\base\core\java\android\view\animation(也即android.view.animation包);
Property Animation,這種動畫是Android 3.0新引進的動畫框架,目前找到的資料比較少,不知道中文譯名用什麼好,暫時稱其為屬性動畫吧。而且原始碼也沒有公開,只是知道使用原始碼包為android.animation。不過通過SDK自帶的APIDemo程式提供的案例可以看出,實現的效果與插間動畫類似,只不過不用通過View控制元件來實現。
逐幀動畫的資源定義檔案可以放置在/res/drawable/下面,也可以放置在/res/anim/資料夾下,由於所放置的位置不同,導致呼叫時也是需要作出區分的。如下語法檔案frameanim.xml
<?xml version="1.0"encoding="utf-8"?>
<animation-listxmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource_name"
android:duration="integer" />
</animation-list>
如果該檔案被放置於res/drawable或res/anim,則呼叫時的情況分別如下
在Xml中的呼叫
@[package:]drawable/frameanim 或@[package:]anim/frameanim
在Java程式碼中的呼叫則如下
R.drawable.frameanim 或 R.anim.frameanim
個人還是比較傾向於將逐幀動畫資源放置在res/drawable下面,摘錄用例如下
在res/drawable/frameanimation.xml中定義瞭如下動畫資源
<?xml version="1.0"encoding="utf-8"?>
<animation-listxmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/a1"android:duration="500" />
<itemandroid:drawable="@drawable/a2" android:duration="500"/>
<item android:drawable="@drawable/a3"android:duration="500" />
<item android:drawable="@drawable/a4"android:duration="500" />
<item android:drawable="@drawable/a5" android:duration="500"/>
<item android:drawable="@drawable/a6"android:duration="500" />
<item android:drawable="@drawable/a7"android:duration="500" />
<item android:drawable="@drawable/a8"android:duration="500" />
<item android:drawable="@drawable/a9"android:duration="500" />
<item android:drawable="@drawable/a10"android:duration="500" />
<item android:drawable="@drawable/a11"android:duration="500" />
<item android:drawable="@drawable/a12"android:duration="500" />
<item android:drawable="@drawable/a13"android:duration="500" />
<item android:drawable="@drawable/a14"android:duration="500" />
<item android:drawable="@drawable/a15"android:duration="500" />
</animation-list>
由於drawable類動畫必須藉助view類物件,簡單點的就是imageview控制元件,為此我們將上述資源用於如下佈局檔案檔案中
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/animation_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/frameanimation" />
<Button
android:id="@+id/animation_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/start_animation" />
<Button
android:id="@+id/one_shot_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/play_once" />
</LinearLayout>
然,在程式碼中就可以直接進行如下程式碼編輯
public class AnimActivity extends Activity
{
/** Called when the activity is first created. */
AnimationDrawable mAd;
Button mPlayBtn;
Button mOneShotBtn;
boolean mIsOneShot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView iv = (ImageView) findViewById(R.id.animation_view);
mAd = (AnimationDrawable) iv.getDrawable();
mPlayBtn = (Button) findViewById(R.id.animation_btn);
mPlayBtn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
startAnimation();
}
});
mOneShotBtn = (Button) findViewById(R.id.one_shot_btn);
mOneShotBtn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
if (mIsOneShot)
{
mOneShotBtn.setText("PlayOnce");
}
else
{
&nb