安卓怎么将运行layer文件中的<item>项中的安卓加载帧动画素材或者补间动画

1. 显示文本
在TextView类中预定义了一些类似HTML的标签,但并不具备HTML标签的全部功能。几个常用的标签如下:
&font&:设置颜色和字体。只支持color和face两个属性。
&big&:设置大号字
&small&:设置小号字。如果&big&和&small&都没有,表示正常字号。
&u&:下划线
&tt&:等宽字体
&br&:换行(行与行之间没有空行,相当于&\n&)
&p&:换行(行与行之间有空行,相当于&\n\n&)。对于带标签的文本,直接使用&\n&无法换行,只能使用&br&或&p&
&a&:链接地址
&img&:插入图像
不能将带这些标签的字符串直接使用TextView.setText方法进行设置,而需要使用Html.fromHtml方法先将带标签的字符串转换成CharSequence对象,然后再使用TextView.setText方法进行设置。
如果想在显示的文本中将URL地址、E-mail地址、电话等特殊内容高亮显示,并在单击时触发相应的动作(URL地址会调用浏览器显示网址,电话会直接在拨号界面显示电话号)可设置&TextView&标签的android:autoLink属性。该属性可设置的值如下:
none:不匹配任何链接(默认值)
web:匹配Web网址
email:匹配E-mail地址
phone:匹配电话号码
map:匹配映射地址
all:匹配所有的链接(即匹配所有的特殊字符串)
只有android:autoLink属性为true时可识别TextView控件中可响应动作(拨号、显示网页等)的文本。如果不设置android:autoLink属性,而且不通过代码设置可响应动作的文本,这就要使用&a&标签来实现可响应动作的文本(还需调用TextView.setMovementMethod方法设置MovementMethod对象,否则单击链接不会有任何动作)。
由于&TextView&标签的android:text属性不能设置特殊的字符,如&&&和&&&,因此,要想在android:text属性中设置这些特殊字符串,需要使用字符串资源(字符串资源支持上面的html标签)。
例如:&string name=&link_text&&&a href=&tel:10086&&打电话&/a&&/string&
&下面看看例子:
运行如下:
代码如下:
TextView tv = (TextView) findViewById(R.id.tv);// 未指定android:autoLink属性 TextView tv2 = (TextView) findViewById(R.id.tv2);// 指定了android:autoLink属性值为all String str = &I love blog,\n&; str += &I love 安卓&; str += &welcome to my blog
&; str += &&; CharSequence charSequence = Html.fromHtml(str); tv.setText(charSequence); // 下面的语句非常重要,没有该语句,虽然可以正常显示
2. 同时显示文本和图像
&img&标签中的src属性指向一个图像地址或者某个图像资源的唯一标识,但系统并不会直接根据src属性的值自动显示图像,解析src属性值的工作需要在ImageGetter.getDrawable方法中完成。ImageGetter是一个接口,在Html.fromHtml方法的如下重载形式中会用到它:
方法原型:public static Spanned fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler);
source:包含Html标签的字符串
imageGetter:ImageGetter对象。当系统解析到&img&标签时就会调用ImageGetter.getDrawable方法,并将src属性值传入getDrawable方法。至于src属性值的具体含义,就要在getDrawable方法中确定了。getDrawable方法返回一个Drawable对象,可从res/drawable资源、SD卡或网络获得图像资源,并封装成Drawable对象。
tagHandler:TagHandler对象。这个参数并不常用,当系统处理每一个标签时都会调用TagHandler.handleTag方法。如果不使用该参数,可将该参数值设为null。
下面看看例子:
运行如下:
代码如下:
public class Main extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv = (TextView) findViewById(R.id.tv); // 定义并初始化一个带标签的字符串 String html = &图1图2图3
& + &图4图5&; // 调用Html.fromHtml方法处理标签,将src属性值转换为Drawable对象 CharSequence cs = Html.fromHtml(html, new ImageGetter() { @Override public Drawable getDrawable(String source) { Drawable d = getResources().getDrawable(getResourceId(source)); // 必须使用Drawable.setBounds方法设置图像的显示区域,否则图像无法显示。setBounds方法的前两个参数表示图像显示区域的左上角坐标,后两个参数表示图像区域的宽度和高度 if (source.equals(&image3&))// 第3个图像文件按50%等比压缩显示 d.setBounds(0, 0, d.getIntrinsicWidth() / 2, d.getIntrinsicHeight() / 2); else // 其他的图像文件按原大小显示 d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); } }, null); tv.setText(cs); // 只要使用了3. 定义子字符串的样式设置字符串中的某个子字符串的样式(变成可单击的链接、设置字体等)需要如下几步:
将原字符串转换成SpannableStringBuilder或SpannableString对象。
获得要设置样式的子字符串在原字符串中的开始位置和子字符串后面的字符的位置,也就是start和end。
创建一个Span对象(所有android.text.style包中的XxxSpan类创建的对象的统称),即子字符串的样式。
使用setSpan方法设置一个Span对象。方法原型:public void setSpan(Object what, int start, int end, int flags);
用处理完的SpannableStringBuilder或SpannableString对象设置相应的控件。
SpannableStringBuilder类对象既可以修改文本内容,又可以将某段文本设置成Span。而SpannableString类对象不允许修改文本,只允许设置Span。
在Android SDK的android.text.style包中提供了很多现成的Span类,下面列出部分Span类的功能:
ClickableSpan:处理单击动作
BackgroundColorSpan:设置字符串的背景色
ForegroundColorSpan:设置字符串的颜色(没有可同时设置背景和文字颜色的Span类)
下面列出setSpan方法的参数flags的部分值的效果:
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE:在当前Span效果的前后输入字符时不应用Span的效果。
Spanned.SPAN_EXCLUSIVE_INCLUSIVE:在Span前面输入的字符不应用Span的效果,在后面输入的字符应用Span效果。
Spanned.SPAN_INCLUSIVE_EXCLUSIVE:在Span前面输入的字符应用Span的效果,在后面输入的字符不应用Span效果。
Spanned.SPAN_INCLUSIVE_INCLUSIVE:在当前Span效果的前后输入字符时都应用Span的效果。
下面看看例子:
例1. 本例实现文本变成可单击的链接。
代码如下:public class Main extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView textView1 = (TextView) findViewById(R.id.textview1); TextView textView2 = (TextView) findViewById(R.id.textview2); String text1 = &显示Activity1&; String text2 = &显示Activity2&; // 将文本转换成SpannableString对象 SpannableString spannableString1 = new SpannableString(text1); SpannableString spannableString2 = new SpannableString(text2); // 将text1中的所有文本设置成ClickableSpan对象,即这段文本可点击,并实现onClick方法 spannableString1.setSpan(new ClickableSpan() { // onClick方法中可编写单击文本时要执行的动作 @Override public void onClick(View widget) { Intent intent = new Intent(Main.this, Activity1.class); startActivity(intent);// 显示Activity1 } }, 0, text1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString2.setSpan(new ClickableSpan() { @Override public void onClick(View widget) { Intent intent = new Intent(Main.this, Activity2.class); startActivity(intent); } }, 0, text1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 使用SpannableString对象设置两个TextView控件的内容 textView1.setText(spannableString1); textView2.setText(spannableString2); // 在单击链接时凡是有要执行的动作,都必须设置相应的MovementMethod对象 textView1.setMovementMethod(LinkMovementMethod.getInstance()); textView2.setMovementMethod(LinkMovementMethod.getInstance()); } }例2. 本例实现设置文本颜色和背景色。
运行如下:
代码如下:public class Main extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView textview = (TextView) findViewById(R.id.textview); String text = &&没有背景&&黄色背景&&绿色字体&\n\n&蓝色背景,红色文字&&; SpannableString spannableString = new SpannableString(text); int start = 6;// “&黄色背景&”字符串的开始位置 int end = 12;// “&黄色背景&”字符串的结束位置 BackgroundColorSpan bcs = new BackgroundColorSpan(Color.YELLOW); spannableString.setSpan(bcs, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); start = 10;// “背景&&绿色字体&”字符串的开始位置 end = 18;// “背景&&绿色字体&”字符串的结束位置 ForegroundColorSpan fcs = new ForegroundColorSpan(Color.GREEN); spannableString.setSpan(fcs, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); start = 20;// “&蓝色背景,红色文字&”字符串的开始位置。每一个&\n&算一个长度 ColorSpan cs = new ColorSpan(Color.RED, Color.BLUE); spannableString.setSpan(cs, start, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); textview.setText(spannableString); } }这里自定义了一个ColorSpan类,使其可以同时设置文字颜色和背景色。该类代码如下:public class ColorSpan extends CharacterStyle { private int mTextC private int mBackgroundC public ColorSpan(int textColor, int backgroundColor) { mTextColor = textC mBackgroundColor = backgroundC } // 该方法在系统开始绘制要设置样式的字符串之前调用,以便修改绘制文字的属性 @Override public void updateDrawState(TextPaint tp) { tp.bgColor = mBackgroundC tp.setColor(mTextColor); } }
1. 设置文本自动换行
Eclipse中文本无法自动换行,可以装一个扩展插件WordWrap,实现文本的自动换行。
安装方法:
使用Eclipse 的自动升级功能,菜单栏选【Help】→【install new Software】,点击Add按钮,然后在&name&中填入&wordwrap&,在&URL&中填入&&,最后按照提示进行安装就可以了。装完后在代码编辑界面点右键,会出现&Word Warp&属性,将这个属性选上就可以实现自动换行了!
1. 配置标识符(Configuration Qualifier)
默认资源目录名后面用连字符(-)连接的部分被称为配置标识符。Android SDK支持的配置标识符如下:
&配置标识符 &标识符值 &描述 &MCC和MNC
mcc310-mnc004
mcc208-mnc00
&MCC(移动国家代码,Mobile Country Code)和可选的MNC(移动网络代码,Mobile Network Code)是从SIM卡中读出的信息。例如,mcc310表示美国的运营商,mcc310-mnc004表示美国的Verizon运营商,mcc208-mnc00表示法国的Orange运营商。
如果设备使用无线连接(Radio Connection)(GSM手机),MCC会从SIM卡读取,同时MNC从设备所连接的网络中读取。
你也可以单独使用MCC(例如,在应用程序中可包含特定国家的法律资源)。如果只想指定语言,可使用语言和地区标识符。 &Language和Region
&语言标识符被定义为两个字母的代码,详细定义可查阅ISO 639-1。区域标识符是可选的,也采用了两个字母的代码(但要在代码前面加一个小写的&r&),详细定义可查看ISO 3166-1-alpha-2的相关内容。
语言和地区代码都不区分大小写。&r&前缀用于区分某个地区,不能单独指定一个区域,也就是说,指定区域必须先指定语言。
如果用户在系统设置中改变了当前的语言,程序在运行时就会改变自身的语言(选择与当前语言相匹配的资源目录读取资源)。 &Layout Direction
&ldltr表示从左到右布局,ldrtl表示从右到左布局。
最低API Level:17 &Smallest Screen Width
&sw&N&dp,其中N表示一个整数。
&最小屏幕宽度的像素。所谓最小屏幕宽度就是Android设备屏幕的最小边的宽度(像素个数)。例如,分辨率是480*800的屏幕最小宽度是480,最小宽度是不会随着屏幕方向的改变而改变的。
最小屏幕宽度不仅包括用户可使用的区域,也包括不可利用的区域(如系统状态栏)。系统会选择一个与当前屏幕最小宽度接近(不能超过)的资源目录。
最低API Level:13 &Screen Width
&w&N&dp,其中N表示一个整数。
&屏幕可使用的最小宽度。这里的宽度是指从屏幕左侧到右侧的宽度。当屏幕方向改变后,可使用的宽度也随之改变。
最低API Level:13 &Screen Height &
&h&N&dp,其中N表示一个整数。
h720dp &屏幕可使用的最小高度。这里的高度是指从屏幕顶端到底端的高度。当屏幕方向改变后,可使用的高度也随之改变。
最低API Level:13 &Screen Size
&屏幕实际的物理尺寸,&也就是屏幕对角线的长度。不过从API Level=13开始,屏幕尺寸已不建议使用,取而代之的是Smallest Screen Width、Screen Width和Screen Height。但如果要开发API Level=13以前版本的,仍需要使用屏幕尺寸。
这4种泛化的屏幕尺寸对应的最小屏幕长宽尺寸(单位dp)如下:
small:320*426
normal:320*470
large:480*640
xlarge:720*960。这种大分辨率要求API Level至少为9。
最低API Level:4 &Screen Ratio
&long:看上去较长的屏幕,如WQVGA、WVGA、FWVGA。
notlong:看上去不长的屏幕,如QVGA、HVGA、VGA。
这只是基于屏幕长宽比较的,与屏幕的方向无关。
最低API Level:4 &Screen Orientation
&port:设备垂直方向
land:设备水平方向 &UI Mode
television
&car:设备放在汽车底座上
desk:设备放在桌面底座上
television:设备通过电视机输出画面。通常看电视时用户会离的比较远,对于较大屏幕的电视,通常会在离电视3米以上的距离观看,因此这种在电视上观看Android画面的过程被称为“10英寸用户体验”,就是用户要离电视屏幕比较远的意思。这种情况主要用于键盘控制或其他非触摸交互的方式(离屏幕好几米远当然不能用触摸的方式了)。
appliance:设备并没有界面(UI),只是为服务提供服务。例如,如果将Android用于机器人的控制,可能就不需要UI,而只需要处理机器人的输入输出即可。appliance要求最低API Level为13。
最低API Level:8 &Night Mode
&night:夜间
notnight:白天
最低API Level:8 &Density
&屏幕每英寸包含的物理像素点个数,通常用dpi(dots per inch)表示。
nodpi:应用于不需要根据屏幕密度进行拉伸的位图资源
ldpi:低密度屏幕,密度约为120dpi
mdpi:中密度(传统的HVGA)屏幕,密度约为160dpi
tvdpi:介于mdpi和hdpi之间的屏幕密度(213dpi左右)。该屏幕密度通常用于智能电视。API Level的最小值为13
hdpi:高密度屏幕,密度约为240dpi
xhdpi:扩展高密度屏幕,密度约为320dpi。API Level的最小值为8
& &Touch Screen
&notouch:设备不支持触摸屏
finger:设备支持触摸屏幕(可能只支持手指,也可能手写笔和手指都支持) &Keyboard State
&keysexposed
keyshidden
&keysexposed:设备的键盘可用(包括软键盘和物理键盘)。设备键盘可分为如下2种情况:
只有软键盘,没有物理键盘或物理键盘被禁用。该值只用于软键盘
只有物理键盘,没有软键盘或软键盘被禁用。该值只用于物理键盘
keyshidden:设备有一个物理键盘,但该物理键盘被隐藏(未被拉出),并且该设备没有可用的软键盘。
keyssoft:设备有一个软键盘,不管这个软键盘是否可用。 &Text Input Method
&nokeys:设备没有用于文本输入的物理按键
qwerty:设备有一个物理querty(与标准计算机键盘相同)键盘,不管这个物理键盘对用户是否可用。
12key:设备有一个12键的物理键盘,不管这个物理键盘是否对用户有用。 &Navigation State
&navexposed
&navexposed:有导航键,并且用户可使用这个导航键
navhidden:导航键不可用(例如,翻盖手机的没有把盖子打开) &Navigation& Method
&nonav:设备没有非触摸的导航方式
dpad:设备通过十字方向键导航
trackball:设备通过轨迹球导航
wheel:设备通过滑轮导航 &Screen Dimension
320x240 &屏幕的物理分辨率,Android中已经不建议使用。 &Platform Version
v14 &API Level 的最低版本。例如,v1表示API Level 1(要求Android 1.0及以上的版本)。
有很多配置标识符的值并不要求物理的值一定相等,而是相近。
可使用多个配置标识符来命名资源目录,多个配置标识符之间用连字符(-)分隔,。
如果在资源目录中包含多个标识符,它们必须按照上表中的顺序排列。
资源目录名中的配置标识符优先级决定了资源目录的优先级。
每一种配置标识符同时只能支持一个值。
资源目录名不区分大小写。
2. 如何得知当前设备的屏幕密度?
由于目前泛化的屏幕尺寸只有4种,所以最直接的方法就是建立4个值资源目录(values-small、values-normal、values-large、values-xlarge),并在这4个目录中建立一个XML文件(文件名可随意取值),然后分别在这4个文件中添加1个key相同,但值不同的字符串资源。
res/values-small/size.xml:&string name=&size&&small&/string&
res/values-normal/size.xml:&string name=&size&&normal&/string&
res/values-large/size.xml:&string name=&size&&large&/string&
res/values-xlarge/size.xml:&string name=&size&&xlarge&/string&
最后使用下面的代码输出size的值,如果输出normal,那说明当前屏幕的尺寸是normal。
Log.e(&screen_size&, getResources().getString(R.string.size));
还可以通过下面的代码获取:
DisplayMetrics metrics = getResources().getDisplayMetrics();int density = metrics.densityD// 获取屏幕密度int widthPixels=metrics.widthP//获取屏幕宽度的物理像素int heightPixels=metrics.heightP//获取屏幕高度的物理像素float densityScale=metrics.//获取当前屏幕密度与标准屏幕密度(160dpi)的比值float fontDensityScale=metrics.scaledD//文字的尺寸(可能会根据具体的字体适当调整这个比值)
3. 在Google Play上限制屏幕尺寸和屏幕密度
指定当前的程序支持的屏幕尺寸、屏幕密度、屏幕最小宽度等信息可在AndroidManifest.xml文件中通过&compatible-screens&标签进行设置,在Android3.2及以后的版本中,还可使用&supports-screens&标签进行设置。如果将该程序发布到Google Play等软件商店,会根据当前浏览软件商店的Android设备显示适合于当前屏幕的Android应用。例如,如果限定当前的Android应用只支持7英寸和10英寸的平板电脑,那么使用手机浏览Google Play时是看不到这个Android应用的。
注意:&compatible-screens&和&supports-screens&标签只能通过软件商店(如Google Play)将不适合当前Android设备屏幕的Android应用隐藏起来,并不能阻止Android应用在不适合的屏幕上运行。例如,只适合7英寸平板电脑的Android应用同样也可以安装在手机上(手动安装),只是在手机上无法通过软件商店看到该程序罢了。如果程序所在的软件商店没有检测到&compatible-screens&和&supports-screens&标签,这两个标签将被忽略。
&compatible-screens&标签没有任何属性,但该标签中可包含任意多个&screen&标签(可不包含&screen&标签)。&screen&标签有如下两个属性:
android:screenSize:设置屏幕尺寸
android:screenDensity:设置屏幕密度
这两个属性必须同时指定,如果只指定一个属性,则该&screen&标签将被忽略。因此,对于同一类屏幕尺寸,要想支持所有的屏幕密度,需要枚举所有的值。
对于Android3.2及以上版本,最好使用&supports-screens&来代替&compatible-screens&标签,显得没有那么麻烦。&supports-screens&可设置Android3.2才开始支持的属性。
&Android SDK支持3种动画:属性动画、帧动画和补间动画。而补间动画又分为移动补间动画、透明度补间动画、缩放补间动画和旋转补间动画,这4种动画都可使用一种叫渲染器的技术。
1. 属性(Property)动画
属性动画从API Level 11(Android3.0)才开始支持。属性动画可使对象的属性值在一定时间间隔内变化到某一个值。例如,在1000毫秒内移动控件的位置(改变x和y的值),在500毫秒内改变alpha属性的值以便改变图像的透明度。属性动画资源文件位于res/animator目录中。&
示例代码如下(res/animator/property_anim.xml):&set xmlns:android=&
&&& android:ordering=&sequentially& &
&&& &objectAnimator
&&&&&&& android:duration=&2000&
&&&&&&& android:propertyName=&y&
&&&&&&& android:valueTo=&300&
&&&&&&& android:valueType=&intType& /&
&&& &objectAnimator
&&&&&&& android:duration=&3000&
&&&&&&& android:propertyName=&x&
&&&&&&& android:valueTo=&220&
&&&&&&& android:valueType=&intType& /&
其中android:ordering属性指定&set&标签中动画的执行顺序,本例是按顺序执行。默认是同时执行(两个&objectAnimator&标签指定的动画同时改变对象属性的值)。因此在本例中property_anim.xml动画文件的功能就是先将对象的y属性值在2000毫秒内变为300,然后再将对象的x属性值在3000毫秒内变为220。
由于Java没有对象的概念,所以这里的属性就是getter和setter方法。例如,x属性会对应读取属性值的getX方法和写属性值的setX方法,所以为了使对象可使用property_anim.xml资源文件控制属性值,在对象中必须要有x和y属性,而且必须是int类型。
下面在Java代码中应用:public class PropertyAnim extends Activity { private B private M @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button); move = new Move(); } // &Move&按钮的单击事件方法 public void onClick_Move(View view) { AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_anim);// 装载属性动画资源 set.setTarget(move);// 设置要控制的对象 set.start();// 开始动画 } // 对Move对象使用属性动画 class Move { public int getY() { } public void setY(int y) { this.y = btn.layout(btn.getLeft(), y, btn.getRight(), y + btn.getMeasuredHeight());// 垂直移动按钮 } public int getX() { } public void setX(int x) { this.x = btn.layout(x, btn.getTop(), x + btn.getMeasuredWidth(), btn.getBottom());// 水平移动按钮 } } }
运行如下:
2. 帧(Frame)动画帧动画类似于电影的播放过程。电影一般每秒会至少播放25幅静态的图像(25帧)。由于人类的视觉暂留,会将一定时间(很短的时间)之前的图像暂存于大脑中,这样在高频率地连续播放静态图像时就会产生动画的效果。根据帧动画的原理,需要在动画资源中定义若干个静态的图像,然后在res/anim目录中建立一个帧动画资源文件。定义帧动画资源文件时应了解如下几点:
帧动画必须用&animation-list&标签作为根节点。
若&animation-list&标签的android:oneshot属性值为true,表示动画只播放一次,否则动画会无限次循环播放。
每一个&item&表示一个静态图像。通过android:drawable属性指定图像资源。
&item&标签的android:duration属性指定了当前图像停留的时间,也就是两幅静态画面之间切换的时间间隔。
示例代码如下(res/anim/frame_animation.xml):
&animation-list xmlns:android=&&&android:oneshot=&false& &&&item android:drawable=&@drawable/anim1& android:duration=&50& /&&&item android:drawable=&@drawable/anim2& android:duration=&50& /&&&item android:drawable=&@drawable/anim3& android:duration=&50& /&&&item android:drawable=&@drawable/anim4& android:duration=&50& /&&&item android:drawable=&@drawable/anim5& android:duration=&50& /&&&item android:drawable=&@drawable/anim6& android:duration=&50& /&&&item android:drawable=&@drawable/anim7& android:duration=&50& /&&&item android:drawable=&@drawable/anim8& android:duration=&50& /&&&item android:drawable=&@drawable/anim9& android:duration=&50& /&&&item android:drawable=&@drawable/anim10& android:duration=&50& /&&&item android:drawable=&@drawable/anim11& android:duration=&50& /&&&item android:drawable=&@drawable/anim12& android:duration=&50& /&&/animation-list& 注:frame_animation2.xml和frame_animation.xml内容相似,只是定义的静态图像文件不同。下面在Java代码中应用:public class FrameAnim extends Activity { private ImageV private AnimationD private AnimationDrawable ad2; private Button addFrameB public void onClick(View view) { switch (view.getId()) { case R.id.btnOneShot:// 只播放一次动画 ad.setOneShot(true);// 动态修改android:oneshot属性值 ad.stop();// 需要先停止动画,然后再开始动画设置才能生效 ad.start();// 开始播放动画 case R.id.btnStartAnim:// 循环播放动画 ad.setOneShot(false); ad.stop(); ad.start(); case R.id.btnStopAnim:// 停止播放动画 ad.stop();// 停止播放第1个帧动画 if (ad2 != null) { ad2.stop();// 如果添加了第2个帧动画,则同时停止第2个帧动画 } case R.id.btnAddFrame:// 在第1个帧动画后添加第2个帧动画 ad2 = (AnimationDrawable) getResources().getDrawable( R.anim.frame_animation2);// 装载资源文件并转换成AnimationDrawable对象 ad.addFrame(ad2, 2000);// 设置第2个帧动画停留的时间(2000毫秒),不管在这段时间内帧动画是否播放完,都将切换到第1个帧动画 addFrameBtn.setEnabled(false); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); addFrameBtn = (Button) findViewById(R.id.btnAddFrame); iv = (ImageView) findViewById(R.id.ivAnimView); iv.setBackgroundResource(R.anim.frame_animation);// 将第1个帧动画设为ImageView控件的背景 ad = (AnimationDrawable) iv.getBackground(); } }
&运行如下:
&帧动画还可通过AnimationDrawable.setAlpha方法设置透明度,setAlpha方法的参数值范围是0~255,0表示不透明,255表示完全透明(动画看不见了)。例如,下面的代码设置了帧动画的透明度为100:
AnimationDrawable ad = (AnimationDrawable) getResources().getDrawable(R.anim.frame_animation);ad.setAlpha(100);&
图像资源文件保存在res/drawable目录中。在图像资源目录中不仅可以存储各种格式(jpg、png、gif等)的图像文件,还可以使用各种XML格式的图像资源来控制图像的状态和行为。
1. 普通图像资源
Android支持3种图像格式:png、jpg和gif。官方推荐使用png格式的图像资源(经常被用在透明或半透明效果中),jpg也可以考虑使用。但gif格式的图像文件并不鼓励使用(由于移动设备性能的限制,目前Android SDK并不支持动画gif,因此,根本没有必要使用gif格式的图像资源)。
假设有一个res/drawable/ball.png图像文件,在布局文件中可使用如下代码引用这个图像资源:
&ImageView&&& android:layout_width=&wrap_content&&&& android:layout_height=&wrap_content&&&& android:src=&@drawable/ball& /&
使用图像资源的Java代码如下:
Drawable drawable = getResources().getDrawable(R.drawable.ball);
2. XML图像资源
XML图像资源实际上就是在XML文件中指定drawable目录中的图像资源。除此之外,还可以额外指定图像的某些属性。例如,图像抖动、图像排列方式等。
XML图像资源使用&bitmap&标签定义。例如,下面的代码定义了一个XML图像资源。
&?xml version=&1.0& encoding=&utf-8&?&&bitmap xmlns:android=&&&&& android:src=&@drawable/icon&&&& android:tileMode=&repeat& /&
&bitmap&标签经常会被使用在图层资源和图像状态资源中。
3. Nine-Patch图像资源
Nine-Patch图像资源与普通图像资源类似,只是Nine-Patch图像资源文件必须以9.png作为文件扩展名,如abc.9.png。
Nine-Patch图像资源的主要作用如下:
防止图像的某一部分被拉伸。
确定将图像作为背景图的控件中的内容显示的位置。
下图是一个png图,在图像的下方有一个突出的尖角。当图像放大或缩小时,要保持这个尖角不变,就要将这个png图变成Nine-Patch格式的图像。
Android SDK本身提供了一个Draw 9-patch工具用来制作Nine-Patch格式的图像。可运行&Android SDK安装目录&\tools\draw9patch.bat命令启动这个工具,并打开上图,界面如下:
可以通过Draw 9-patch工具在png图的四周绘制1个像素粗的直线。上边缘和左边缘的直线分别表示图像在水平和垂直方向可拉伸的范围。如果在水平和垂直方向的某个区域不需要拉伸,可以不绘制相应的直线。如上图像中的小尖角不需要拉伸,因此,小尖角上方未绘制直线。
Nine-Patch格式图像右边缘和下边缘的直线分别表示图像所在控件中内容的显示范围。内容只在右边缘和下边缘绘制直线的区域显示。表示内容显示范围和拉伸范围的两组直线有一个重要的区别,就是表示内容显示范围的直线中间不能断开,而表示拉伸范围的直线中间可以断开。
Nine-Patch图像资源与普通图像资源的使用方法相同。在引用时只写文件名,省略&.9.png&。
通常很多控制图像局部拉伸的场景都会使用Nine-Patch格式的图像。例如,有两个TextView控件的背景图分别设置了Nine-Patch格式和普通格式的图像,效果如下:
&4. XML Nine-Patch图像资源
Nine-Patch图像资源也有与其对应的XML图像资源,这一点与普通图像资源类似。只是使用&nine-patch&标签来引用Nine-Patch格式的图像,而且属性比&bitmap&标签少了很多。示例代码如下:
&?xml version=&1.0& encoding=&utf-8&?&&nine-patch xmlns:android=&&&&& android:dither=&false&&&& android:src=&@drawable/cloud& /&
&5. 图层(Layer)资源
图层资源有些类似于&FrameLayout&,所不同的是&FrameLayout&标签中可以包含任意的控件,而图层资源中的每一层只能包含图像。定义图层资源必须使用&layer-list&标签作为资源文件的根节点,&layer-list&标签中可以包含多个&item&标签,每一个&item&标签表示一个图像,最后一个&item&标签会显示在最顶层(这一点与&FrameLayout&标签相同)。
&item&标签有4个控制偏移量的属性,分别是android:top(顶端偏移的像素)、android:left(左侧)、android:right(右侧)、android:bottom(底端)。
下面的代码通过&item&指定了一个图像:
&item android:drawable=&@drawable/icon&/&
默认情况下,图像会尽量充满显示图像的视图。因此,显示的图像可能会被拉伸。为避免图像拉伸,可在&item&标签中使用&bitmap&标签引用图像,代码如下:
&item&&&& &bitmap&&&&&&& android:gravity=&center&&&&&&&& android:src=&@drawable/icon& /&&/item&
下面是一个完整的图层资源的例子(源代码文件res/drawable/layer.xml):
&&?xml version=&1.0& encoding=&utf-8&?&&layer-list xmlns:android=&& &&&& &item android:drawable=&@drawable/frame&/&&&& &item android:left=&60dp&&&&&&&&& &bitmap android:gravity=&left& android:src=&@drawable/edit& /&&/item&&&& &item&&&&&&&& &bitmap android:gravity=&center& android:src=&@drawable/diary& /&&/item&&/layer-list&
下面在TextView标签中使用这个图层资源:
&TextView&&& android:layout_width=&match_parent&&&& android:layout_height=&wrap_content&&&& android:background=&@drawable/layer& /&
图层的显示效果如下所示:
所有放到res/values目录中的资源都属于值资源(可以存放在任意的XML文件中)。
&1. 字符串(String)资源
&字符串资源需要在res/values目录中的xml文件中定义(任何一个文件都可以)。
(1)普通字符串
&普通字符串资源使用&string&标签定义,示例代码如下:
&string name=&hello&&Hello!&/string&
在布局文件中使用字符串资源的代码如下:
&TextView&&& android:layout_width=&wrap_content&&&& android:layout_height=&wrap_content&&&& android:text=&@string/hello& /&
在代码中使用字符串资源的代码如下:
String str = getResources().getString(R.string.hello);
(2)字符串数组
字符串数组资源由&string-array&标签定义,在&string-array&标签中包含的若干&item&标签表示字符串数组元素。示例代码如下:
&string-array name=&friend&&&&& &item&CuiNa&/item&&&& &item&KangWei&/item&&&& &item&SiYi&/item&&/string-array&
在布局文件中使用字符串数组资源的代码如下:
&CustomWidget&&& android:layout_width=&wrap_content&&&& android:layout_height=&wrap_content&&&& android:array_text=&@array/friend& /&
在代码中引用字符串数组的代码如下:
String[ ] str = getResources().getStringArray(R.array.friend);
注意:不能用字符串数组资源设置接收字符串的属性,例如,android:text,因为这样系统会直接将字符串数组资源的ID值当做文本传给该属性。应该用字符串数组资源设置那些可以接收字符串数组资源的属性。例如,CustomWidget是一个自定义控件,android:array_text是一个自定义的属性,可以接收字符串数组资源。
(3)复数字符串
在某些自然语言中不同的数字在使用方法上会有所不同。例如,在英文中,如果说一本书,会说one book,如果说两本书,会说two books。当数量大于1时,会在名词后面加s或变成其他复数形式(不可数名词和专属名词除外),在这种情况下就需要考虑不同数字的字符串资源。
复数字符串资源为这种情况提供了解决方案。需要用&plurals&标签定义复数字符串,并使用&item&标签指定具体处理哪一类数字的复数字符串。示例代码如下:
&plurals name=&numberOfApple&&&&& &item quantity=&one&&One apple&/item&&&& &item quantity=&other&&%d apples&/item&&/plurals&
其中quantity属性的值除了one和other外,还可以是zero、two、few和many。
使用复数字符串资源可以使用getQuantityString方法,该方法有两个重载形式:
方法原型:public String getQuantityString(int id, int quantity) throws NotFoundE
public String getQuantityString(int id, int quantity, Object... formatArgs) throws NotFoundE
id表示复数字符串资源的ID
quantity表示具体的数字,例如,1对应quantity属性值的&one&,2对应quantity属性值的&two&
formatArgs表示复数字符串资源的参数
引用复数字符串的Java代码如下:
//引用数字为1的复数字符串资源String str = getResources().getQuantityString(R.plurals.numberOfApple, 1);
// 引用数字为other的复数字符串资源,调用时向other资源传递一个参数值(20)String str2 = getResources().getQuantityString(R.plurals.numberOfApple, 20, 20);
(4)在字符串中使用引号
字符串中的值虽然可以任意指定,但遇到特殊符号时,如双引号、单引号,就需要采取特殊的方法进行处理。
如果是单引号('),可使用转义符(\)或用双引号(&)将整个字符串括起来。如果是双引号,可在双引号前使用转义符。示例代码如下:
&!-- 输出 you're my lover --&&string name=&str&&&you're my lover&&/string&&string name=&str2&&you\'re my lover&/string&&!-- 输出&you too& --&&string name=&str3&&\&you too\&&/string&
(5)用占位符格式化字符串
String.format(String format, Object... args)方法可格式化带占位符的字符串。因此,只要在字符串资源中插入占位符就可使用String.format方法格式化字符串资源。format方法要求占位符用%1、%2、……%n表示。其中第n个占位符与format方法的n+1个参数值对应。示例代码如下:
&!-- $s表示该占位符要求传入字符串,$d表示该占位符要求传入整数 --&&string name=&str&&Hello, %1$s! you have %2$d new messages.&/string&
格式化字符串资源的Java代码:
String str=String.format(getResources().getString(R.string.str), &xiaomin&,18);
(6)用HTML标签格式化字符串资源
字符串资源支持一些HTML标签,因此,可直接在字符串资源中使用这些HTML标签格式化字符串。示例代码如下:
&string name=&welcome&&Welcome to &b&Android&/b&!&/string&字符串资源支持如下的HTML标签:
&b&:粗体字
&i&:斜体字
&u&:带下划线的文字
有时需要同时使用HTML标签和占位符格式化字符串,但使用String.format方法格式字符串,会忽略字符串中所有的HTML标签。为使format方法可格式化带HTML标签的字符,需要使用Html.fromHTML方法先处理一下字符串。& 示例代码如下:
&string name=&welcome&&Hello, %1$s! you have &b&%2$d new messages&/b&.&/string&
注意:由于需要使用Html.fromHTML方法处理字符串,因此HTML标签中的&&&需要使用&&&表示(&&&可直接使用)。
使用字符串资源的Java代码:
String str=String.format(getResources().getString(R.string.welcome), &xiaomin&,18);
CharSequence cs=Html.fromHtml(str);
如果format的某个参数值包含HTML的特殊字符,如&&&、&&&,可使用下面的代码先格式化这个参数值,再使用format方法格式化字符串:
String username=TextUtils.htmlEncode(username);// username中包含HTML的特殊字符
String str=String.format(getResources().getString(R.string.welcome), username, 18);
CharSequence cs=Html.fromHtml(str);
&2. 整数(Integer)资源
整数资源使用&integer&标签设置,示例代码如下:
&integer name=&width&&100&/integer&&integer name=&height&&200&/integer&
在资源文件中使用下面的代码引用整数资源:
&TextView&&& android:layout_width=&@integer/width&&&& android:layout_height=&@integer/height& /&
下面是引用整数资源的Java代码:
int width = getResources().getInteger(R.integer.width);int height = getResources().getInteger(R.integer.height);
3. 尺寸(Dimension)资源
尺寸资源是由一系列的浮点数组成的资源,&dimen&标签用来定义尺寸资源。示例代码如下:
&dimen name=&size_sp&&30sp&/dimen&&dimen name=&size_in&&1.5in&/dimen&
从上面的代码可看出,在尺寸值后面是尺寸单位。Android支持如下6种尺寸单位:
px:表示屏幕实际的像素。例如,320*480的屏幕在横向有320个像素,在纵向有480个像素。
in:表示英寸,是屏幕的物理尺寸,每英寸等于2.54厘米。例如形容手机屏幕大小,经常说3.2(英)寸、4(英)寸就是指这个单位。这些尺寸是屏幕的对角线长度。如果手机的屏幕是3.2英寸,表示手机的屏幕(可视区域)对角线长度是3.2*2.54=8.128厘米。
mm:表示毫米,是屏幕的物理尺寸。
pt:表示一个点,是屏幕的物理尺寸,大小为1英寸的1/72。
dp:与密度无关的像素,这是一个基于屏幕物理密度的抽象单位。密度可以理解为每英寸包含的像素点个数(单位是dpi),1dp实际上相当于密度为160dpi的屏幕的一个点。也就是说,如果屏幕的物理密度是160dpi时,dp和px是等效的。现在用实际的手机屏幕说明一下,一块拥有320*480分辨率手机屏幕,如果宽度是2英寸、高度是3英寸,这块屏幕的密度就是160dpi。如果屏幕大小未变,而分辨率发生了变化,例如,分辨率由320*480变成了480*800,这时屏幕的物理密度就变大了(大于160dpi)。这就意味着屏幕每英寸可显示更多的像素点,屏幕的显示效果就更细腻了。假设一个按钮的宽度使用dp作为单位,在160dpi时设为160dp,而在更高的dpi下(如320dpi),按钮宽度看上去和160dpi时的屏幕一样。这是由于系统在发现屏幕的密度不是160dpi时,会计算一个转换比例,然后用这个比例与实际设置的尺寸相乘就得出新的尺寸。计算比例的方法是目标屏幕的密度除以160。如果目标屏幕的密度是320dpi,那么这个比例就是2。如果按钮的宽度是160dp,那么在320dpi的屏幕上的宽度就是320个像素点(dp是抽象单位,在实际的屏幕上应转换成像素点)。从这一点可以看出,dp可以自适应屏幕的分辨率。不管屏幕分辨率如何变化,屏幕上控件的相对位置和尺寸总会保持不变。如果将按钮的宽度设成160px,那么在320dpi的屏幕上仍然会是160个像素点,看上去按钮宽度只是160dpi屏幕的一半。Android官方建议设置表示宽度、高度、位置等属性时应尽量使用dp作为尺寸单位。除了使用dp,也可以使用dpi,它们是等效的。要注意的是,dpi表示密度,而dpi=dp。在使用时不要弄混了。
sp:与比例无关的像素。这个单位与dp类似。不过除了自适应屏幕密度外,还会自适应用户设置的字体。因此,Android官方推荐在设置字体大小时(如android:textSize属性)应尽量使用sp作为尺寸单位。
可使用下面3种方法获取尺寸资源,这些方法会根据相应的尺寸单位返回与其对应的像素值,这3个方法的区别是返回值的类型不同:
float size = getResources().getDimension(R.dimen.size_in);// 对size采用舍去的方式返回对应的整数,例如,size=25.6,则size2=25int size2 = getResources().getDimensionPixelOffset(R.dimen.size_in);// 对size采用四舍五入的方式返回对应的整数,例如,size=25.6,则size3=26int size3 = getResources().getDimensionPixelSize(R.dimen.size_in);
如果想直接获取尺寸大小(不转换成像素),可使用下面的代码:
TypedValue outValue = new TypedValue();// getValue方法的第3个参数如果为true,表示即使资源值引用了另外的资源,系统会通过递归的方法获取最终的资源值getResources().getValue(R.dimen.size_in, outValue, true);// 由于getValue方法并未直接返回尺寸资源的值,所以需要使用complexToFloat方法进行转换。此例得到的value值为1.5float value = plexToFloat(outValue.data);&&
4. 布尔(Boolean)资源
布尔资源使用&bool&标签设置,标签值只能是true或false。示例代码如下:
&bool name=&is_clickable&&true&/bool&&bool name=&is_right&&false&/bool&
在资源文件中使用如下方式引用布尔资源:
&TextView&&& android:layout_width=&match_parent&&&& android:layout_height=&100dp&&&& android:clickable=&@bool/is_clickable& /&
下面是引用布尔资源的Java代码:
boolean isRight=getResources().getBoolean(R.bool.is_right);
5. 颜色(Color)资源
颜色资源用于指定颜色值,使用&color&标签设置。示例代码如下:
&color name=&opaque_red&&#f00&/color&&color name=&translucent_red&&#80ff0000&/color&
在资源文件中使用颜色资源的代码如下:
&TextView&&& android:layout_width=&wrap_content&&&& android:layout_height=&wrap_content&&&& android:text=&明天会更好&&&& android:textColor=&@color/translucent_red& /&
下面是引用颜色资源的Java代码:
int color = getResources().getColor(R.color.opaque_red);
Android允许将颜色值作为资源保存在资源文件中。保存在资源文件中的颜色值用井号(#)开头,Android支持如下4种颜色值表示方式:
其中R、G、B表示三原色,也就是红、绿、蓝,A表示透明度,也就是Alpha值。A、R、G、B的取值范围都是0~255。R、G、B的取值越大,颜色越深。如果R、G、B都等于0,表示的颜色是黑色,都为255,表示的颜色是白色。R、G、B三个值相等时表示灰度值。R、G、B总共可表示的24次方)种颜色。A取0时表示完全透明,取255时表示不透明。如果采用前两种颜色值表示法,A、R、G、B的取值范围是0~15,这并不意味着是颜色范围的256个值的前15个,而是将每一个值扩展成两位。例如,#F00相当于#FF0000;#A567相当于#AA556677。从这一点可以看出,#RGB和#ARGB可设置的颜色值并不多,它们的限制条件是颜色值和透明度的8位字节的高4位和低4位相同。其他的颜色值必须使用后两种形式设置。
ID资源实际上就是android:id属性的值,使用&item&标签设置。示例代码如下:
&item name=&text& type=&id&/&
资源文件中引用ID资源的代码如下:
&TextView&&& android:id=&@id/text&&&& android:layout_width=&wrap_content&&&& android:layout_height=&wrap_content& /&
通常在设置android:id属性时都会在&@&和&id&之间加一个&+&,这个&+&的含义是如果ID资源不存在,系统会自动创建一个ID资源,如果ID资源存在,系统会忽略&+&。通过这种策略避免在设置android:id属性值时都要定义ID资源的繁琐方式。
7. 整数数组(Integer-Array)资源
整数数组资源用于存储一组整数,用&integer-array&标签设置。示例代码如下:
&integer-array name=&num&&&&& &item&1&/item&&&& &item&6&/item&&&& &item&9&/item&&/integer-array&
引用整数数组资源的Java代码如下:
int[ ] num = getResources().getIntArray(R.array.num);
8. 类型数组(Typed-Array)资源
类型数组资源可以将其中资源作为数组存储,因此也可以称为资源数组资源。示例代码如下:
&array name=&icons&&&&& &item&@drawable/icon1&/item&&&& &item&@drawable/icon2&/item&&/array&
引用类型数组资源的Java代码如下:
TypedArray icons = getResources().obtainTypedArray(R.array.icons);Drawable drawable = icons.getDrawable(0);
1. 创建选项菜单(Options Menu)
Activity.onCreateOptionsMenu方法用来创建选项菜单
方法原型:public boolean onCreateOptionsMenu(Menu menu);
调用Menu.add方法可以添加一个选项菜单项。该方法有4种重载方式:
方法原型:public MenuItem add(int titleRes);
public MenuItem add(CharSequence title);
public MenuItem add(int groupId,int itemId,int order,int titleRes);
public MenuItem add(int groupId,int itemId,int order,CharSequence title);
groupId:菜单项的分组ID。该参数一般用于带选项按钮的菜单。参数值可以是负整数、0和正整数。
itemId:当前添加的菜单项的ID。参数值可以是负整数、0和正整数。
order:菜单显示顺序。Android系统在显示菜单项时,根据order参数的值按升序从左到右、从上到下显示菜单项。参数值必须是0和正整数,不能为负整数。
titleRes或title:菜单项标题的字符串资源ID或字符串。
如果使用add方法的前两种重载形式,groupId、itemId和order三个参数的值都为0。这时菜单项的显示顺序就是菜单项的添加顺序。
如果想为菜单项设置图像,可使用MenuItem.setIcon方法,
1. Android的五大布局
android:layout_width和android:layout_height是必选属性,所有的视图标签都有这两个属性。
(1)框架布局(FrameLayout)
所有添加到这个布局中的视图都以层叠的方式显示,第一个添加到框架布局中的视图显示在最底层,最后一个添加到框架布局中的视图被放在最顶层,上一层的视图会覆盖下一层的视图。
(2)线性布局(LinearLayout)
android:orientation属性的默认值是horizontal。
如果是水平线性布局,子视图只能通过android:layout_gravity属性设为垂直居中,而对于垂直线性布局,子视图只能通过android:layout_gravity属性设为水平居中。
layout_weight属性需要设置一个非负整数值,如果该属性值大于0,线性布局会根据水平或垂直方向以及不同视图的layout_weight属性值占所有视图的layout_weight属性值之和的比例为这些视图分配自己所占用的区域,视图将按相应比例拉伸。如果layout_weight属性值为0,视图会按原大小显示(不会被拉伸)。对于其余layout_weight属性值大于0的视图,系统将会减去layout_weight属性值为0的视图的高度或宽度,再用剩余的高度或宽度按相应的比例来分配每一个试图所占的高度和宽度。
(3)相对布局(RelativeLayout)
(4)表格布局(TableLayout)
表格布局可将视图按行、列进行排列。一个表格布局由一个&TableLayout&标签和若干个&TableRow&标签组成。
表格布局在实现行列效果中并不常用,一般会使用GridView控件来代替表格布局。
(5)绝对布局(AbsoluteLayout)
绝对布局并不建议使用,因为Android设备的屏幕大小和长宽比例有很大差异,使用绝对布局很难适应各种屏幕尺寸。
2.&布局别名
本地化目录也就是满足特定要求的资源文件存放的目录,例如,特殊的屏幕尺寸、不同的Android版本、不同的语言环境、不同的屏幕方向等。如果系统发现并没有满足当前特定要求的本地化资源目录,就会从默认的资源目录中寻找资源。例如,本地化资源目录只有res/values-zh(中文)和res/values-en(英文),而当前的语言环境是法文,但并没有res/values-fr目录,所以系统会在默认的资源目录(res/values)寻找相应的字符串资源。
布局别名就是为不同布局文件指定同一个资源ID,以便在不同环境下系统可以使用同一个布局资源ID访问不同的布局资源。使用布局别名必须要注意布局文件的引用只能放到本地化资源目录中,而不能放到默认的资源目录中。
下面看看例子:
假设在res/layout目录中有两个布局文件:main_layout.xml和main_layout_en.xml,并且在主窗口中使用setContentView方法(R.layout.main_layout)将main_layout.xml与当前窗口关联。现在建立一个res/values-en目录(英文环境下使用该目录中的资源),然后在该目录下建立一个refs.xml文件(资源文件名可以任意命名),最后再refs.xml文件中输入如下的内容:
&?xml version=&1.0& encoding=&utf-8&?&&resources&&&& &!-- 为main_layout_en.xml文件指定一个名为main_layout的别名 --&&&& &item name=&main_layout& type=&layout&&@layout/main_layout_en&/item&&/resources& 如果当前环境正好是英文,系统就会使用res/values-en目录中的资源,所以会为main_layout_en.xml文件指定一个别名。如果别名正好与某一个布局文件的资源ID相同,那么就相当于修改该资源文件ID的指针,也就是说如果在英文环境下,R.layout.main_layout引用的不再是main_layout.xml,而是main_layout_en.xml。扩展学习:如果目录中的文件太乱,需要整理,通常会采用两种方式。第1种方式最容易想到,也是最常用的,就是建立若干个目录,然后分门别类地将目录的文件放到这些刚建立的目录中。但还有另外一种方法,就是并不移动源目录中的文件,而是为每一个文件建立一个索引(可以将这些索引数据存储在数据库或其他文件中),然后对这些索引进行分组和管理。这么做的好处是并不需要移动文件,而且同一个文件还可以属于不同的类别。如果要采用第1种方式,就需要将文件所属的每个类别对应的目录都复制一份同样的文件,这样不仅浪费存储空间,也不易于管理。本地化的方式与管理目录中文件的方式类似,可以将满足不同环境的资源文件放到相应的本地化资源目录中,也可以将资源文件统一放到一起,而在不同的本地化资源目录中添加别名引用,布局别名就是采用了后一种方式。
3. 重用布局&在一个复杂的应用程序中往往同样的布局要在多处使用。当然,最笨的办法是在所有需要的地方重复编写这些布局。这种方法固然可行,不过一旦需要修改布局,维护其一致性恐怕就要增加很大的工作量(有的布局可能会被重复使用上百次,甚至更多)。在布局文件中可以使用&include&标签(注意,include首字母要小写)很好地解决上述问题,通过这个标签,可以在一个布局文件中引用另外一个布局文件。这样我们就可以将在多处使用的布局单独放在一个或多个布局文件中,然后在使用到这些布局文件时用&include&标签来引用它们。例如,我们有一个叫a.xml的布局文件,在另一个布局文件中需要使用2次,那么可以使用如下的布局代码:&LinearLayout
&&& android:layout_width=&match_parent&
&&& android:layout_height=&match_parent& &
&&& &!-- 引用2次a --&
&&& &include android:id=&@+id/a1& layout=&@layout/a& /&
&&& &include android:id=&@+id/a2& layout=&@layout/a& /&
&/LinearLayout&
&include&标签只有layout属性是必选的,该属性不需要android命名空间作为前缀。layout属性值是布局文件的资源ID。在上面的代码中&include&标签还使用了一个android:id属性,实际上,该属性指定的是a.xml布局文件中根节点的android:id属性值。如果根节点已经设置了android:id属性值,那么&include&标签的android:id属性值将覆盖a.xml布局文件中根节点的android:id属性值。&include&标签还可以覆盖被引用的布局文件根节点的所有与布局相关的属性,也就是以&android:layout_&开头的属性,例如,android:layout_width、android:layout_height等。通过覆盖属性值,可以使被引用的布局文件中的视图拥有不同的布局风格。
注意:如果想覆盖布局的尺寸,必须同时覆盖android:layout_width和android:layout_height。不能只覆盖其中一个属性,否则对这两个属性值的覆盖无效。 4. 优化布局我们可使用Android SDK自带的一个分析视图类层次的工具,如下图:点击右侧红色箭头所指的那个图标按钮可打开这个工具,然后会在界面的左侧显示真机(如果是用真机调试程序)或模拟器(如果是用模拟器调试程序)中运行的程序的当前界面(此处是手机的桌面程序)的视图类层次结构(如下图):
&下面看个简单例子:
main.xml代码如下:
&?xml version=&1.0& encoding=&utf-8&?&&FrameLayout xmlns:android=&&&&& android:layout_width=&match_parent&&&& android:layout_height=&match_parent& &&&& &Button&&&&&&& android:layout_width=&wrap_content&&&&&&&& android:layout_height=&wrap_content&&&&&&&& android:layout_gravity=&right&&&&&&&& android:text=&右边& /&&&& &Button&&&&&&& android:layout_width=&wrap_content&&&&&&&& android:layout_height=&wrap_content&&&&&&&& android:layout_gravity=&center_horizontal&&&&&&&& android:text=&中间& /&&/FrameLayout& 用分析视图类层次工具分析如下:
&思考:明明在布局文件中只使用了一个&FrameLayout&标签,为什么该&FrameLayout&标签上层还有一个&FrameLayout&标签?
~~实际上,任何一个布局文件,无论根节点是&LinearLayout&、&RelativeLayout&还是&FrameLayout&,Android系统都会在上一层添加一个&FrameLayout&。也就是说,任何的布局文件都会被包含在&FrameLayout&标签中。
为了解决这个问题,可以使用&merge&标签代替&FrameLayout&标签,系统在遇到&merge&标签时,会自动忽略这个标签,这样就只剩下一个&FrameLayout&标签了,把以上代码改为以下:
&?xml version=&1.0& encoding=&utf-8&?&&merge xmlns:android=&&&&& android:layout_width=&match_parent&&&& android:layout_height=&match_parent& &&&& &Button&&&&&&& android:layout_width=&wrap_content&&&&&&&& android:layout_height=&wrap_content&&&&&&&& android:layout_gravity=&right&&&&&&&& android:text=&右边& /&&&& &Button&&&&&&& android:layout_width=&wrap_content&&&&&&&& android:layout_height=&wrap_content&&&&&&&& android:layout_gravity=&center_horizontal&&&&&&&& android:text=&中间& /&&/merge&
用分析视图类层次工具重新分析如下,可看到视图类的层次结构中少了一个&FrameLayout&标签:
注意:&merge&标签虽然能使视图类层次结构更简洁(即优化),但该标签只对&FrameLayout&标签有效,因为当&merge&标签被忽略时,上层还有一个&FrameLayout&标签。&merge&不能使用在其他的布局中,这是因为系统是不会将&merge&转换成&LinearLayout&、&RelativeLayout&标签的,再说系统也不知道如何转换。所以如果使用&merge&代替&LinearLayout&、&RelativeLayout&等布局标签,这些标签就消失了,这样就相当于仍然使用了&FrameLayout&标签。5. 动态装载布局如果要动态装载、添加视图,通常在主窗口类中调用LayoutInflater.inflate方法创建一个新的视图对象。可调用Activity.getLayoutInflater方法获得LayoutInflater类的对象。方法原型:public View inflate(int resource,ViewGroup root)
resource表示要装载的视图资源ID
root表示要装载的视图的父视图。如果装载的视图没有父视图,该参数值为null。
下面看看例子:
程序运行如下:
MainActivity.java代码如下:public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout parent = (LinearLayout) getLayoutInflater().inflate( R.layout.activity_main, null);//装载主窗口使用的布局 for (int i = 1; i &= 10; i++) { View view = getLayoutInflater().inflate(R.layout.item, null);//由于view是动态添加的,所以inflate方法的第2个参数值为null TextView textView = (TextView) view.findViewById(R.id.textview); textView.setText(&text& + i); parent.addView(view);//动态添加每一行的视图对象 } setContentView(parent); } }activity_main.xml代码如下:
&LinearLayout xmlns:android=&&&&& android:layout_width=&match_parent&&&& android:layout_height=&match_parent&&&& android:orientation=&vertical& &
&/LinearLayout&
item.xml代码如下:
&TextView xmlns:android=&&&&& android:id=&@+id/textview&&&& android:layout_width=&wrap_content&&&& android:layout_height=&wrap_content& /& 6. 动态设置布局属性在第5节动态装载布局的例子中,如果将activity_main.xml文件中&LinearLayout&标签的android:gravity属性值设为&center_horizontal&,或将item.xml文件中&TextView&标签的android:layout_gravity属性值设为&center_horizontal&,或将这两个属性值设为&right&,运行后你会发现,动态添加的10个视图并没有居中或右对齐。原因是动态添加视图时并不会采用静态方式设置布局,而要想重新设置布局属性,就需要使用LayoutParams类。但要注意,由于主窗口布局使用的是LinearLayout布局,所以要使用android.widget.LinearLayout.LayoutParams类。修改后的MainActivity.java代码如下(布局代码未修改,运行修改后的程序,所有的控件都会居中显示):public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout parent = (LinearLayout) getLayoutInflater().inflate( R.layout.activity_main, null); for (int i = 1; i &= 10; i++) { View view = getLayoutInflater().inflate(R.layout.item, null); TextView textView = (TextView) view.findViewById(R.id.textview); textView.setText(&text& + i); // 创建LayoutParams对象 android.widget.LinearLayout.LayoutParams lp = new android.widget.LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); // 设置gravity字段的值 lp.gravity = Gravity.CENTER_HORIZONTAL; // 动态添加视图时指定父视图的布局参数 parent.addView(view, lp); } setContentView(parent); } }&7. 从右到左布局(RTL Layout)从Android4.2开始,Android SDK支持一种从右到左(RTL,Right-to-Left)UI布局的方式,尽管这种布局方式经常被使用在诸如阿拉伯语、希伯来语等环境中,中国用户很少使用。不过在某些特殊用途中还是很方便的。所谓RTL,就是指按平常习惯在左的视图都会在右侧,在右侧的视图都会在左侧。例如,在线性布局中第1个子视图默认都是在左上角的,如果采用RTL布局,默认就在右上角了。RTL布局默认是关闭的,如果想使用RTL布局,首先要在AndroidManifest.xml文件中将&application&标签的android:supportsRtl属性值设为&true&,然后需要将相应视图标签的android:layoutDirection属性值设为&rtl&。注意:假设一个水平线性布局中有两个&TextView&标签:TextView1和TextView2。TextView1位于窗口的左上角,而TextView2在TextView1的右侧,到TextView1的距离是100dp。如果当前是默认布局方式(LTR,Left-to-Right),只需要将TextView2的android:layout_marginLeft属性值设为&100dp&即可。但如果当前是RTL布局方式,TextView1在窗口的右上角,TextView2跑到了TextView1的左侧,此时则应该设置TextView2的android:layout_marginRight属性。这样就会造成LTR和RTL两种布局模式中UI排列的混乱。为了解决这个问题,在Android4.2中新加了如下两个布局属性:
android:layout_marginStart:如果在LTR布局模式下,该属性等同于android:layout_marginLeft。如果在RTL布局模式下,该属性等同于android:layout_marginRight。
android:layout_marginEnd:如果在LTR布局模式下,该属性等同于android:layout_marginRight。如果在RTL布局模式下,该属性等同于android:layout_marginLeft。
1. 真机调试时,apk安装好后无法自动启动,但可以手动启动,也可以被其它程序访问。
Console输出如下:
主窗口声明如下:
&activity android:name=&com.zxm.b.MainActivity& &&&& &intent-filter&&&&&&&& &action android:name=&android.intent.action.MAIN& /&&&&&&&& &category android:name=&android.intent.category.LAUNCHER& /&&&&&&&& &action android:name=&zxm& /&&&&&&&& &category android:name=&android.intent.category.DEFAULT& /&&&& &/intent-filter&&/activity&
解决办法:把以上声明改为以下:
&activity android:name=&com.zxm.b.MainActivity& &&&& &intent-filter&&&&&&&& &action android:name=&android.intent.action.MAIN& /&&&&&&&& &category android:name=&android.intent.category.LAUNCHER& /&&&&&& &&& &/intent-filter&&&& &intent-filter&&&&&&&& &&&&&&& &action android:name=&zxm& /&&&&&&&& &category android:name=&android.intent.category.DEFAULT& /&&&& &/intent-filter&&/activity& &
1.& 真机调试时,apk安装好后无法自动启动,外部程序也访问不到该窗口,但可以手动启动。
Console输出如下:
&我的主窗口声明如下:
&activity android:name=&com.zxm.b.MainActivity& &&&& &intent-filter&&&&&&&& &action android:name=&android.intent.action.MAIN& /&&&&&&&& &category android:name=&android.intent.category.LAUNCHER& /&&&&&&&& &action android:name=&455& /&&&& &/intent-filter&&/activity& 解决办法:去掉上面的第二个&action&标签。或者另外再写一个过滤器,把第二个&action&标签放在该过滤器里。}

我要回帖

更多关于 安卓加载帧动画素材 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信