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工具也是根據具體文件夾名稱調用不同的規則來可視化編輯和呈現。
使用eclipse IDE提供的框架來創建資源
由於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代碼中調用的。
字符串常量資源(string)
字符串資源位於/res/values目錄下,一般定義為/res/values/strings.xml文件中(文件名隨意,但是目錄是固定的),主要定義的是應用程序需要用到的字串資源,這和Symbian的字串資源規划類似,不過更加進步了些。當然,你非要在代碼中使用字串也可以,但那種方式並不是推薦的。字串資源有String、String Array和Quantity Strings (Plurals)三類,其各自語法和用例稍微有些區別
String語法
<?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
String用例
假設有個資源文件為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);
String Array的語法
<?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用例
假設有個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);
Quantity Strings語法
<?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用例
假設有個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);
String資源的注意項
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);
整數常量資源(Integers)
整數常量在C/C++通常是放在代碼里面,android將整型常量、Bool常量和數組常量等等都可以放到XML資源文件中,后面具體介紹這些資源時就不再做展開了。一般整數常量被放置在/res/values/integers.xml中,同樣文件名可以隨意,但是目錄必須固定在/res/values/下
Integer語法
<?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
Integer用例
假設整數常量放置在/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);
Integer Array語法
<?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
Integer Array用例
假設整數數組放置在/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常量資源
Typed Array資源有點類似於Symbian中瘦模板類的,用於存放多種不同類型資源數組的資源,本來想將這個資源放后面講解,但是前面提供了一系列數組案例,就一並將這個數組也提前羅列下吧。該資源一般放置於/res/values/arrays.xml中
Typed Array語法
<?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用例
假設有兩個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來獲得更多的詳情。
布爾常量資源(bool)
該資源一般定義在/res/values/bools.xml中。
bool語法
<?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資源用例
假設有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);
Dimension常量資源
該資源定義跟屏幕顯示相關的一些尺寸常量,一般保存在/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,作為和文字相關大小單位。
dimension資源定義語法
<?xml version="1.0"encoding="utf-8"?>
<resources>
<dimen name="dimension_name">dimension</dimen>
</resources>
dimension資源用例
假設定義了一個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);
顏色常量資源(color)
顏色常量通常被定義在/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等,所以最后再涉及這兩類資源的介紹。
狀態顏色列表資源(color state list)
該資源被放置於/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"/>
布局資源(Layout)
布局資源是放置於/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);
}
}
結果程序運行后,顯示如下圖所示的結果
菜單資源(menu)
菜單資源位於/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;
}
}
動畫資源(animation)
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
{
mOneShotBtn.setText("Play Repeatly");
}
mAd.setOneShot(!mIsOneShot);
mIsOneShot = !mIsOneShot;
}
});
}
/**
* 通過AnimationDrawable的start函數播放動畫,
* stop函數停止動畫播放,
* isRunning來判斷動畫是否正在播放。
*/
public void startAnimation() {
if (mAd.isRunning()) {
mAd.stop();
} else {
mAd.stop();
mAd.start();
}
}
}
補間動畫語法
該類資源定義必須在res/anim目錄下。補間動畫源自flash動畫制作,即給出兩個關鍵幀在中間需要做“補間動畫”,才能實現圖畫的運動;插入補間動畫后兩個關鍵幀之間的插補幀是由計算機自動運算而得到的。所以相對補間動畫,需要的參數有起始幀、結束幀、變化方式和變化速度,Android SDK提供了四類基本變化方法,具體詳見如下語法
<?xml version="1.0"encoding="utf-8"?>
<setxmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float"
android:duration="int" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
以上四種變化方法,分別對應四個變化函數
AlphaAnimation(float fromAlpha, float toAlpha)
功能:構建一個透明度漸變動畫
參數:fromAlpha為動畫起始幀的透明度,toAlpha為動畫結束幀的透明度(0.0表示完全透明,1.0表完全不透明)
RotateAnimation(float fromDegrees, float toDegrees, int pivotXType,float pivotXValue, int pivotYType, float pivotYValue)
功能:構建一個旋轉畫面的動畫
參數:fromDegrees為開始幀的角度,toDegrees是結束幀的角度(負的度數表示逆時針角度,比如fromDegrees =180,toDegrees= -360則開始幀位置是圖像繞圓心順時針轉180度,逆時針旋轉至540度);后面四個參數決定了旋轉的圓心位置,pivotXType和pivotYType確定了圓心位置的類型,pivotXValue和pivotYValue是具體的位置坐標系數,類型參數有Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF和Animation.RELATIVE_TO_PARENT三種,當absolute時表示絕對坐標,此時pivotXValue和pivotYValue就是屏幕上的絕對像素坐標位置,即(android:pivotX="20" android:pivotY="20" )表示圓心為屏幕(20,20)這個點;relative_to_self表示相對自身,即假設自身為(0,0,20,20)的矩形控件,那么(android:pivotX="50%" android:pivotY="50%")表示圓心的位置為控件的中心,即絕對坐標(10,10);relative_to_parent顯然就是先對父窗口的比例圓心,用(android:pivotX="50%p"android:pivotY="50%p")來表示繞父窗口中心點旋轉。
ScaleAnimation(float fromX, float toX, float fromY, float toY, intpivotXType, float pivotXValue, int pivotYType, float pivotYValue)
功能:構建一個縮放動畫
參數:fromX,fromY,toX,toY分別表示起始幀和結束幀相對於源圖像在X和Y方向的伸縮大小,0.0表示縮小到無,小於1.0表示縮小,1.0表示正常大小,大於1.0表示放大;后面四個參數與旋轉的參數等同,表示縮放是的參考點。
TranslateAnimation(int fromXType, float fromXValue, int toXType,float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
功能:構建一個位移動畫
參數:前面四個參數確定一個起始坐標,后面四個參數確定一個結束坐標,這些坐標位置是采用了類似旋轉圓心的算法。
上面語法中沒有涉及到android:interpolator,這個就是變化速度,目前android系統提供了如下一些速度變化器。
Interpolator class |
Resource ID |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
詳情還是參考android.view.animation包中相關的源碼吧。
下面再說下補間動畫的創建步驟(下面步驟考慮到復雜變化,所以引入了set,如果單一變化可以不用set對象)
1.創建一個AnimationSet對象。
2.根據需要創建相應的Animation對象
3.根據軟件動畫的需求,為Animation對象設置相應的數據。
4.將Animation對象添加到AnimationSet對象當中。
5.使用控件對象開始執行AnimationSet
補間動畫用例
補間動畫的示例源碼變化較多,在這里就不詳細羅列,大家可以參看Android開發揭秘案例
也可以參看如下鏈接
http://blog.sina.com.cn/s/blog_78c913e30100w6cd.html
http://www.ophonesdn.com/article/show/185
http://www.ophonesdn.com/article/show/186
http://www.ophonesdn.com/article/show/322
屬性動畫語法
屬性動畫一般要求資源定義文件位於/res/animator/下面,但是如果將其放置在res/anim下面也是允許的。比如在res/anim/propertyanimations.xml文件中進行類似如下定義
<set
android:ordering=["together" | "sequentially"]>
<objectAnimator android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<set>
...
</set>
</set>
那么就可以在XML中對其進行如下調用
@[package:]anim/propertyanimations
在Java代碼中可以對其進行如下調用
R.anim.propertyanimations
屬性動畫用例
其實屬性動畫的操作,通過3.0 SDK自帶的例子API demo,感覺屬性動畫能做的事情,補間動畫也能做,只不過屬性動畫,可以直接針對圖像或drawable資源,當然也可以是widget控件,但是補間動畫必須借助widget控件來實現。
具體用例還是參看android SDK3.0 自帶的例子程序API demo中的ApiDemos\src\com\example\android\apis\animation\AnimationLoading.java等案例。
可繪制資源(Drawable資源)
其實上面用到的逐幀動畫,就是可繪制資源的中的一種,繪制資源涉及的資源類型比較多,詳細列表說明如下
資源類型 |
資源描述 |
Bitmap File |
圖像文件( .png 、 .jpg 或 .gif ) |
XML Bitmap |
為圖像文件增加了描述的XML文件(當然描述跟下面羅列的類型不一樣) |
Nine-Patch File |
一種可基於Content伸縮的PNG文件(.9.png) |
Layer List |
定義了一組按順序繪制可繪制資源的XML文件 |
State List |
定義了因不同狀態而調用不同圖像文件的XML文件 |
Level List |
定義了不同level圖片的XML文件,主要用於類似電量、信號等類似情況 |
Transition Drawable |
定義了兩張圖片,讓其在規定時間內漸變的XML文件 |
Inset Drawable |
定義一個內嵌圖片的XML(可設置四邊距),通常給控件做內插背景用 |
Clip Drawable |
定義一個圖片的XML,該圖片資源可以根據level等級來剪取需要顯示比例內容 |
Scale Drawable |
定義一個圖片的XML,該圖片可以根據level等級進行縮放 |
Shape Drawable |
定義了繪制顏色和漸變的幾何形狀的XML文件 |
Animation Drawable |
定義了逐幀動畫的XML文件,在上面動畫資源中講解過了 |
Color |
定義了繪制顏色值的XML,感覺同values內的color一樣,只是調用形式有點區別 |
綜合來說,可繪制資源可以大致分為三類:
直接圖片資源類,該類都是圖像文件,有Bitmap File和Nine-Patch File,而且圖像文件,API文檔雖然說.png 、 .jpg 或 .gif 格式都支持,但是也提議 .png (最佳)、 .jpg (可接受)、 .gif (不要)的原則,另外考慮到aapt編譯資源時會考慮優化,所以如果圖像要絕對保真,還是將圖像文件放置在res/raw目錄下的比較好;
圖像描述類,該類涉及對一個或多個圖像文件進行添加配置和重新定義,都是XML資源描述文件,其中包括Layer List、State List、Level List、Transition Drawable、Inset Drawable、Clip Drawable、Scale Drawable、Animation Drawable這幾類,通常這些資源或被用作控件view的填充圖像,或被用作控件view的背景;
直接繪圖類,該類也是資源定義XML文件,主要是Shape Drawable類和color類。
由於資源細分類型眾多,對於直接圖片類資源就不做展開介紹了,對於圖像描述類資源,只選取了Clip Drawable和Scale Drawable兩類的用例來簡單說明下,對於直繪類則采用了Shape Drawable類的用例來簡單介紹,其它可詳細參閱API文檔。
Clip Drawable用例
首先有一個圖像文件l5.jpg被放置於res/drawable中,另有一個clip drawable資源定義文件res/drawable/clip.xml,內容如下:
<?xml version="1.0"encoding="utf-8"?>
<clipxmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/l5"
android:clipOrientation="vertical"
android:gravity="left" />
該xml資源正好被main.xml中的一個控件ImageView調用,具體如下所示
<ImageView
android:id="@+id/clipimage"
android:background="@drawable/clip"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
假如不在java代碼中進行控制,那么ImageView將顯示不出背景圖像來,我們對其進行如下調用
ImageView clipview = (ImageView) findViewById(R.id.clipimage);
//這里控件用android:background,調用就用getBackgroud函數
ClipDrawable drawable = (ClipDrawable) clipview.getBackground();
drawable.setLevel(drawable.getLevel() + 2000);
結果就會在ImageView上顯示剪切過了的小圖。
Scale Drawable用例
如上例一樣,還是那個l5.jpg圖片,在res/drawable中定義了一個scale.xml資源文件,具體內容如下
<?xml version="1.0"encoding="utf-8"?>
<scalexmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/l5"
android:scaleGravity="center_vertical|center_horizontal"
android:scaleHeight="80%"
android:scaleWidth="80%" />
表示上述圖片在資源中就已經被縮放了80%,該資源被main.xml中的另一個Imageview控件使用
<ImageView
android:id="@+id/scaleimage"
android:src="@drawable/scale"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
同樣該資源假如不通過代碼在用戶界面上也是顯示不出來的,具體調用代碼類似如下:
ImageView scaleview = (ImageView) findViewById(R.id.scaleimage);
//這里控件用android:src,調用就用getDrawable函數
ScaleDrawable scaledrawable = (ScaleDrawable) scaleview.getDrawable();
scaledrawable.setLevel(1000);
結果就會在Imageview上顯示一個縮小了l5的圖像
Shape Drawable資源用例
有一個shapeDrawable資源定義在res/drawable/buttonstyle.xml,具體內容如下:
<?xml version="1.0"encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape>
<!-- 漸變 -->
<gradient
android:startColor="#ff8c00"
android:endColor="#FFFFFF"
android:type="radial"
android:gradientRadius="50" />
<!-- 描邊 -->
<stroke
android:width="2dp"
android:color="#dcdcdc"
android:dashWidth="5dp"
android:dashGap="3dp"/>
<!-- 圓角 -->
<corners
android:radius="2dp"/>
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp"/>
</shape>
</item>
<item android:state_focused="true" >
<shape>
<gradient
android:startColor="#ffc2b7"
android:endColor="#ffc2b7"
android:angle="270"/>
<stroke
android:width="2dp"
android:color="#dcdcdc" />
<corners
android:radius="2dp"/>
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp"/>
</shape>
</item>
<item>
<shape>
<solid android:color="#ff9d77"/>
<stroke
android:width="2dp"
android:color="#fad3cf" />
<corners
android:topRightRadius="5dp"
android:bottomLeftRadius="5dp"
android:topLeftRadius="0dp"
android:bottomRightRadius="0dp"
/>
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp"/>
</shape>
</item>
</selector>
該Shape繪制資源,被main.xml中的兩個button所調用,代碼如下所示
<ImageButton
android:id="@+id/button"
android:src="@drawable/buttonstyle"
android:layout_width="136dp"
android:layout_height="110dp"/>
<ImageButton
android:id="@+id/button1"
android:background="@drawable/buttonstyle"
android:layout_width="136dp"
android:layout_height="110dp"/>
這個就不需要用java代碼了,結果如下圖所示
風格和主題資源(style&theme)
風格和主題的語法其實是一樣的,只是運用環境不一樣。
Theme是針對窗體級別的,改變窗體樣式;
Style是針對窗體元素級別的,改變指定控件或者Layout的樣式。
Android系統的themes.xml和style.xml(位於/base/core/res/res/values/)包含了很多系統定義好的style,一般使用系統的就可以了,需要擴展也是建議在里面挑個合適的,然后再繼承修改。
風格和主題資源語法
Style&theme資源定義文件被放置在res/values下面,具體語法形式如下:
<?xml version="1.0"encoding="utf-8"?>
<resources>
<style name="style_name"
parent="@[package:]style/style_to_inherit">
<itemname="[package:]style_property_name">style_value</item>
</style>
</resources>
調用時可以通過@[package:]style/style_nam或者R.style.style_name來實現。
風格和主題資源用例
下邊是主題的一個例子:
<?xml version="1.0"encoding="utf-8"?>
<resources>
<style name="CustomTheme">
<itemname="android:windowNoTitle">true</item>
<item name="windowFrame">@drawable/screen_frame</item>
<itemname="windowBackground">@drawable/screen_background_white</item>
<itemname="panelForegroundColor">#FF000000</item>
<itemname="panelBackgroundColor">#FFFFFFFF</item>
<itemname="panelTextColor">?panelForegroundColor</item>
<itemname="panelTextSize">14</item>
<itemname="menuItemTextColor">?panelTextColor</item>
<itemname="menuItemTextSize">?panelTextSize</item>
</style>
</resources>
我們用了“@”符號和“?”符號來應用資源。“@”符號表明了我們應用的資源是前邊定義過的(或者在前一個項目中或者在Android 框架中)。“?”表明了我們引用的資源的值在當前的主題當中定義的。通過引用在<item>里邊定義的名字可以做到(panelTextColor 用的顏色和panelForegroundColor中定義的一樣 ),這種技巧只能用在XML資源當中。
在程序中使用主題的方法有兩類,一類是主題應用在一個activity中,可以在Java代碼中修改如下:
protected void onCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setTheme(R.style.CustomTheme);
setContentView(R.layout.linear_layout_3);
}
也可以在AndroidManifest.xml中修改具體Activity的主題屬性,代碼如下
<activityandroid:theme=”@style/CustomTheme”>
如果要使主題應用至整個應用,那么就必須在mainfest.xml中應用主題:
打開應用代碼的AndroidManifest.xml文件,編輯<application>標簽,讓其包含android:theme屬性,值就是需要調用的主題的名字,代碼如下:
<applicationandroid:theme=”@style/CustomTheme”>
至此我們將Android用到的資源基本都介紹了下,至於res/xml和res/raw文件下的資源,前者通過Resources.getXML()獲取資源文件,后者通過Resources.openRawResource()獲得資源文件,具體文件解析和處理在這里就不做展開了。
資源文件中一些屬性概念的區分
在資源中有很多相似或者有點容易混淆的屬性概念,在這個小結的末尾對碰到的補充說明下。
android:gravity VS android:layout_gravity
gravity是用於對齊的標簽,其中android:gravity屬性是針對控件view內容的限定。比如一個button上面的text,你可以設置該text在view的靠左或靠右等位置,該屬性起到這個作用。
android:layout_gravity屬性是用來設置該控件相對於父view 的位置的限定。比如一個button在linearlayout里,你想把該button放在靠左或靠右等位置就可以通過該屬性來設置。
padding VS margin
padding是填充的意思,指的是控件view中的內容(content)與控件view邊緣的距離,也即控件內邊距的屬性關系;而margin表示的是控件外邊距的關系,即控件view與ViewGroup的距離關系,在相對布局中控件與控件之間的相對位置距離關系。
目前先小結到這里,對於屬性概念方面的內容,后面用到了再繼續追加記錄。
View的顯示狀態GONE,VISIBLE和INVISIBLE區別
很多網友可能會發現View類的設置顯示狀態setVisibility方法有三種情況,分別為GONE、VISIBLE和INVISIBLE,它們之間到底有哪些區別呢? Android123給大家舉個簡單的例子。可能很多網友會發現有些Android應用的下面包含了AdMob或Adsense廣告條,如果這個View我們設置為GONE則消失,該廣告條看不見也不占用位置。而INVISIBLE則代表廣告條那塊是空白,但仍然沾着他布局高和寬的位置,而VISIBLE 就是標准顯示時的狀態。