本篇博客内容是对Android中Resource资源的介绍。大部分内容从Android官方网站上获取,对其进行分析、理解和再加工最终得到下面的内容。本文最后的style部分介绍了视图控件是如何根据系统主题设定自己的样式,如字体大小、颜色和视图背景等信息,该部分对于以后分析各种View控件大有益处。请尊重他人劳动成果,请勿随意剽窃,转载请注明,谢谢!
Animation
一、属性动画
文件位置在res/animator/filename.xml中。Java代码中使用R.animator.filename获取;xml文件中使用@[package:]animator/filename方式获取资源。
文件中只能有一个根元素<set>, <objectAnimator>, or <valueAnimator>。一般都是使用<set>它能够内嵌
<set>, <objectAnimator>, or <valueAnimator>。下面对各类常用标签进行简单介绍
<set>
- 该标签有一个android:ordering属性,控制内嵌在其中的动画展示顺序
<objectAnimator>
- 用于在指定的一段时间类控制一个Object的特定属性
- android:propertyName属性;如android:propertyName="alpha",目标对象需要有对应的setAlpha()方法
- android:valueTo属性;动画最终停留的值
- android:valueFrom属性;动画起始的值
- android:duration属性:动画生命时间
- android:valueType属性:属性数据类型
<animator>
- 代表ValueAnimator,用于在一段时间类修改一个值。除了没有android:propertyName属性其它同<objectAnimator>基本一致
示例
-------------------xml文件内容------------------------
res/animator/property_animator.xml:
<set android:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
----------------------Java客户代码------------------------------
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();
二、补帧动画(渐变动画)
文件位置在res/drawable/filename.xml中。Java代码中使用R.drawable.filename获取;xml文件中使用@[package:]drawable.filename方式获取资源。文件中只能有一个根元素<animation-list>,然后内部嵌套很多<item
>元素
。下面对各类常用标签进行简单介绍
<animation-list>
- android:oneshot属性为true只反映一次,false则循环放映
<item>
- android:drawable属性指定这一帧所使用的图片
- android:duration属性指定这一帧停留的时间
示例
-------------------xml文件内容------------------------
res/anim/rocket.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>
----------------------Java客户代码------------------------------
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();
Drawable
一、Bitmap File
文件位置在res/drawable/filename.png (.png, .jpg, or .gif)中。文件格式推荐为png,jpg次之,gif不推荐。这里的文件都会被转换成bitmapDrawable对象。Java代码中使用R.drawable.filename获取;xml文件中使用@[package:]drawable/filename方式获取资源。
二、Layer List
文件位置在res/drawable/filename.xml中。Java代码中使用R.drawable.filename获取;xml文件中使用@[package:]drawable/filename方式获取资源。用于显示一组drawable试图。
示例
-------------------xml文件内容------------------------
res/drawable/layers.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:src="@drawable/android_red"
android:gravity="center" />
</item>
<item android:top="10dp" android:left="10dp">
<bitmap android:src="@drawable/android_green"
android:gravity="center" />
</item>
<item android:top="20dp" android:left="20dp">
<bitmap android:src="@drawable/android_blue"
android:gravity="center" />
</item>
</layer-list>
----------------------客户代码------------------------------
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/layers" />
三、State List
文件位置在res/drawable/filename.xml中。Java代码中使用R.drawable.filename获取;xml文件中使用@[package:]drawable/filename方式获取资源。根据当前View的状态显示不同的背景样式。根目录必须为<selector>,下面对常用元素进行说明。
<selector>
- xmlns:android 定义xml域名空间其值必须为"http://schemas.android.com/apk/res/android".
<item>
- 定义不同状态对应不同的drawable
- android:drawable:其值是对一个drawable资源的引用
- android:state_pressed、android:state_focused、android:state_selected等等状态
示例
-------------------xml文件内容------------------------
res/drawable/button.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="@drawable/button_focused" /> <!-- focused -->
<item android:state_hovered="true"
android:drawable="@drawable/button_focused" /> <!-- hovered -->
<item android:drawable="@drawable/button_normal" /> <!-- default -->
</selector>
----------------------客户代码------------------------------
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/button" />
四、Level List
文件位置在res/drawable/filename.xml中。Java代码中使用R.drawable.filename获取;xml文件中使用@[package:]drawable/filename方式获取资源。用于管理一组Drawable,Obejct可以通过setLevel()显示不同Drawable,比如电池的状态。根目录必须为<level-list>,下面的元素为<item>;
<item>
- android:drawable:所对应的Drawable资源
- android:maxLevel:当前Drawable能显示的level最大值
- android:minLevel:当前Drawable能显示的level最小值
示例
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/status_off"
android:maxLevel="0" />
<item
android:drawable="@drawable/status_on"
android:maxLevel="1" />
</level-list>
五、Shape Drawable
文件位置在res/drawable/filename.xml中。Java代码中使用R.drawable.filename获取;xml文件中使用@[package:]drawable/filename方式获取资源。定义一个几何图形。根目录必须为<shape>。
<shape>
- xmlns:android:xml域名空间通常值为"http://schemas.android.com/apk/res/android".
- android:shape:几何形状,"rectangle"、"oval"、"line"(需要通过<stroke> 指定宽度)、"ring" 对应矩形、椭圆、线、环。
- 当android:shape="ring"时:
- android:innerRadius:环的内部半径
- android:thickness:环的厚度
- 当android:shape="rectangle"时:
- <corners>该标签用于设置每个角上的角度
- android:radius:所有角的半径;也有android:topLeftRadius、android:topRightRadius等针对不同角设置不同的弧度
<solid>
- 形状填充颜色,只有一个android:color属性指定颜色
- 当前形状的渐变颜色
- android:angle:渐变的角度,0从左到右,90从上到下
- android:startColor:起始颜色
- android:centerColor:开始到结束中间的颜色
- android:endColor:结束颜色
- android:type:渐变样式,线性还是?
<size>
- 形状大小
- android:height:高度
- android:width:宽度
<stroke>
- 当前形状的边
- android:width:宽度
- android:color:颜色
示例
-------------------xml文件内容------------------------
res/drawable/gradient_box.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#FFFF0000"
android:endColor="#80FF00FF"
android:angle="45"/>
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<corners android:radius="8dp" />
</shape>
----------------------客户代码------------------------------
<TextView
android:background="@drawable/gradient_box"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
此外还有Transition Drawable、Clip Drawable、Scale Drawable这里就不再介绍了。
Menu
被应用在Options Menu, Context Menu, or submenu中,通过MenuInflater进行加载。文件位置在res/menu/filename.xml中。Java代码中使用R.menu.filename获取;xml文件中使用@[package:]menu.filename方式获取资源。<menu>必须为其根目录,能够内嵌<item> 和 <group> e两种元素
<item>
- android:id:定义一个唯一的id
- android:title:菜单标题
- android:titleCondensed:如果系统嫌弃前面内容太长可以选择使用这里的值
- android:icon:图标
- android:onClick:指定其点击事件处理方法,不设置也可以在onOptionMenu中处理点击事件,这里指定的方法必须声明在Activity中,且是public,而且参数为 MenuItem。
- android:showAsAction:控制合适如何显示当前item。
- ifRoom表明有空间则放,没空间存入overflowMenu中;
- withText同时显示一个字符,可以显示一个"|“字符作为两个Action之间的界限。
- never、always一个永不一个总是显示到ActionBar中。
- collapseActionView:不展开当前Item关联的Action View。
- android:actionLayout:Layout use as action View
- android:actionViewClass:类的全称,如android.widget.SearchView
- android:actionProviderClass:共享信息使用,如android.widget.ShareActionProvider
- android:orderInCategory:当前item在group中的权重,值越大越往后
<group>
- 管理一组item
示例
-------------------xml文件内容------------------------
res/menu/example_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/item1"
android:title="@string/item1"
android:icon="@drawable/group_item1_icon"
android:showAsAction="ifRoom|withText"/>
<group android:id="@+id/group">
<item android:id="@+id/group_item1"
android:onClick="onGroupItemClick"
android:title="@string/group_item1"
android:icon="@drawable/group_item1_icon" />
<item android:id="@+id/group_item2"
android:onClick="onGroupItemClick"
android:title="@string/group_item2"
android:icon="@drawable/group_item2_icon" />
</group>
<item android:id="@+id/submenu"
android:title="@string/submenu_title"
android:showAsAction="ifRoom|withText" >
<menu>
<item android:id="@+id/submenu_item1"
android:title="@string/submenu_item1" />
</menu>
</item>
</menu>
----------------------Java客户代码------------------------------
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.example_menu, menu);
return true;
}
public void onGroupItemClick(MenuItem item) {
// One of the group items (using the onClick attribute) was clicked
// The item parameter passed here indicates which item it is
// All other menu item clicks are handled by onOptionsItemSelected()
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------下面的xml文件都是存放在values目录下的,前面都是定义在特定的animator、drawable、menu目录中----------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
String
一、String
文件位置在res/values/filename.xml中。Java代码中使用R.string.string_name获取;xml文件中使用@string/string_name方式获取资源。根目录必须是<resources>
<string>
- name:string的名字
示例
-------------------xml文件内容-----------------------
res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello!</string>
</resources>
----------------------客户代码------------------------------
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
二、String Array
文件位置在res/values/filename.xml中。Java代码中使用R.array.string_array_name获取。根目录必须是<resources>
<string-array>
- name:字符数组的名字
- <item>:数组元素中的值
示例
-------------------xml文件内容-----------------------
res/values/strings.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>
----------------------Java客户代码------------------------------
Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);
Bool
-------------------xml文件内容-----------------------
res/values-small/bools.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="screen_small">true</bool>
<bool name="adjust_view_bounds">true</bool>
</resources>
----------------------Java客户代码------------------------------
Resources res = getResources();
boolean screenIsSmall = res.getBoolean(R.bool.screen_small);
----------------------客户代码------------------------------
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="@drawable/logo"
android:adjustViewBounds="@bool/adjust_view_bounds" />
Color
-------------------xml文件内容-----------------------
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>
----------------------Java客户代码------------------------------
Resources res = getResources();
int color = res.getColor(R.color.opaque_red);
----------------------客户代码------------------------------
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@color/translucent_red"
android:text="Hello"/>
Dimension
-------------------xml文件内容-----------------------
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>
----------------------Java客户代码------------------------------
Resources res = getResources();
float fontSize = res.getDimension(R.dimen.font_size);
----------------------客户代码------------------------------
<TextView
android:layout_height="@dimen/textview_height"
android:layout_width="@dimen/textview_width"
android:textSize="@dimen/font_size"/>
Integer
-------------------xml文件内容-----------------------
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>
----------------------Java客户代码------------------------------
Resources res = getResources();
int maxSpeed = res.getInteger(R.integer.max_speed);
Integer Array
-------------------xml文件内容-----------------------
res/values/integers.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);
Style
文件位置在res/values/filename.xml中。xml文件中使用 @[package:]style/style_name方式获取资源。根目录必须是<resources>
<style>
- name:style的名字
- parent:父类,可为空
<item>
- 定义样式的单独属性,是<style>标签下的子标签
- name:属性attribute名字
示例
-------------------xml文件内容-----------------------
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomText" parent="@style/Text">
<item name="android:textSize">20sp</item>
<item name="android:textColor">#008</item>
</style>
</resources>
----------------------客户代码------------------------------
<?xml version="1.0" encoding="utf-8"?>
<EditText
style="@style/CustomText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello, World!" />
样式的定义与使用
attr:
定义自定义属性。如
<attr name="custom_attr1" format="string" />
<attr name="custom_attr2" format="string" />
定义一个attr就会在R文件里面生成一个Id
使用自定义属性
int[] custom_attrs = {R.attr.custom_attr1,R.custom_attr2};
styleable:
attr不依赖于styleable,styleable只是为了方便attr的使用,有一个分组的概念,属性的使用范围更加明确。定义一个styleable,我们可以在R文件里自动生成一个int[],数组里面的int就是定义在styleable里面的attr的id。
定义
<declare-styleable name="custom_attrs">
<attr name="custom_attr1" format="string" />
<attr name="custom_attr2" format="string" />
</declare-styleable>
使用
TypedArray typedArray = context.obtainStyledAttributes(set,R.styleable.custom_attrs);
obtainStyledAttributes()
参数指定从哪里获取到指定的属性
obtainAttributes(AttributeSet set, int[] attrs)
- 从layout设置的属性集中获取attrs中的属性
- set:表示从layout文件中直接为这个View添加的属性的集合
- 还记得View构造器的参数(Context context, AttributeSet set)?
obtainStyledAttributes(int[] attrs)
- 直接从Theme中读取属性
obtainStyledAttributes(int resId,int[] attrs)
- 从资源文件定义的style中读取属性
- resId:直接从资源文件中定义的某个样式中读取
obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
- defStyleAttr:是自定义一个可以在Theme中配置样式的关键,如TextView
- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
- //在主题中设置textview的style
- <item name="android:textViewStyle">@style/textviewstyle</item>
- </style>
- <style name="textviewstyle" parent="android:style/Widget.TextView">
- <!--指定一些属性-->
- </style>
- public TextView(Context context, AttributeSet attrs) {
- //指定属性textViewStyle为defStyleAttr,然后系统会去搜索Theme中你为这个 属性配置的style
- this(context, attrs, com.android.internal.R.attr.textViewStyle);
- }
- defStyleRes:直接从资源文件中定义的某个样式中读取
综上样式的数据来源有四个:set,defStyleAttr,NULL,defStyleRes。优先级如下
set -> defStyleAttr(主题可配置样式) -> defStyleRes(默认样式) -> NULL(主题中直接指定)。下面说人话,查找样式顺序如下:
- View的layout中声明的属性。如app:custom_attr="value"或者android:style="@style/myStyle"
- 当前App或者Activity的Theme中配置样式,需要在obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) 方法中声明(红色字体)
- obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) 方法中(红色字体)声明的资源中的属性
- 当前App或者Activity的Theme中声明的属性
下面给出一个样例
一、声明attr
res/values/styles.xml
<declare-styleable name="custom_attrs">
<attr name="custom_color1" format="color"></attr>
<attr name="custom_color2" format="color"></attr>
<attr name="custom_color3" format="color"></attr>
<attr name="custom_color4" format="color"></attr>
<attr name="custom_color5" format="color"></attr>
</declare-styleable>
<attr name="custom_style" format="reference"></attr>
二、定义attr
---------------------partA-----------------------------
res/layout/mylayout.xml
<com.exmp.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:style="@style/myStyle"
app:custom_color1="#ff000000"
>
</com.exmp.MyCustomView>
res/values/styles.xml
<style name="myStyle">
<item name="custom_color1">#ff111111</item>
<item name="custom_color2">#ff111111</item>
</style>
-----------------------PartB------------------------------
res/values/styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
//配置style
<item name="custom_style">@style/custom_theme</item>
//直接在主题中指定
<item name="custom_color1">#ff444444</item>
<item name="custom_color2">#ff444444</item>
<item name="custom_color3">#ff444444</item>
<item name="custom_color4">#ff444444</item>
<item name="custom_color5">#ff444444</item>
</style>
res/values/styles.xml
<style name="custom_theme">
<item name="custom_color1">#ff222222</item>
<item name="custom_color2">#ff222222</item>
<item name="custom_color3">#ff222222</item>
</style>
------------------------PartC----------------------------
<style name="default_style">
<item name="custom_color1">#ff333333</item>
<item name="custom_color2">#ff333333</item>
<item name="custom_color3">#ff333333</item>
<item name="custom_color4">#ff333333</item>
</style>
三、对应java客户代码
public MyCustomView(Context context) {
this(context,null);
}
public MyCustomView(Context context, AttributeSet set) {
this(context, set, R.attr.custom_style); //对应PartB
}
public LinearRecyclerView(Context context, AttributeSet set, int defStyle) {
super(context, set, defStyle);
final TypedArray a = context.obtainStyledAttributes(
set, R.styleable.custom_attrs, defStyle, R.style.default_style); //对应PartC
}
TypedArray中获取的属性值分别是:
custom_color1=#ff000000 //布局文件中直接指定,优先级最高
custom_color2=#ff111111 //布局同通过style指定,也包含在set中,优先级第二
custom_color3=#ff222222 //布局通过主题中配置风格style
custom_color4=#ff333333 //由系统Theme直接指定的
custom_color5=#ff444444
注意:TypedArray主要有两个作用,第一是内部去转换attrid和属性值数组的关系;第二是提供了一些类型的自动转化。可以将其看成一个Json数据
<include>/<merge>
<include>
是将整个布局文件(xml)作为一个View添加到父布局文件中,<include>中的view有自己单独的视图结构。可以将include看成是把xml文件整个原封不动的添加到父布局中,没有修改任何参数。可以重写include中的最外层根目录的属性,但是必须重写<layout_height><layout_width>两个属性。
<merge>
出现在被复用的布局文件中,最后还是通过include标签将其添加到父布局中,但是添加到父布局中之后,可以看成<merge>标签自动消失。此处的布局文件直接嵌入到父布局文件中。前面的<include xml>是通过一个根(如FrameLayout)嵌套进父布局中的。
Reference:
https://developer.android.com/guide/topics/resources/available-resources.html(所有resource、android官方资料)