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 就是标准显示时的状态