第三章:Creating Applications and activities-(六)外部资源

1.1 外部资源

不论你是什么开发环境,对于开发来说最好的做法就是不要将资源(例如图片等)路径这些整合到代码中。Android支持将这些资源外部化,范围包括一些简单的值,如字符串、颜色和更加复杂的图片资源、主题和动画。也许最强大的外部资源是布局。

通过外部资源化,可以让维护、升级和管理变得更加容易,这会让你更加容易定义不同的资源值去支持不同的硬件和国际化。

接下来你会了解到Andriod是如何为不同的硬件、语言以及位置动态的选择资源。这就需要你去为不同的语言、国家、屏幕以及键盘创建不同的资源。当应用启动后,Android会自动选择资源而不用编写任何代码。

这样你就可以基于屏幕大小更改布局,并且可以定制基于语言和国家定制提示信息。

1.1.1 创建资源

应用的资源都被存储在项目的 res/ 文件夹目录下。在这个文件夹中每种可用的资源类型都被存储在子文件夹下。

如果你使用ADT插件向导创建一个项目,它会为你创建一个res文件夹,它下边的子文件夹包括valuesdrawable- ldpi,drawable-mdpi,drawable-hdpi,和一个默认的layout布局资源,应用图片和分别定义的string 资源。如图3-4所示。

注意那三个Drawable资源文件夹创建了三种不同的图标,分别是低、中、高 DPI显示方式。

九个主要的资源类型有不同的文件夹:simple valuesDrawableslayoutsanimationsstylesmenussearchablesXMLraw resources。当你的应用被打包的时候,这些资源就会尽可能高效的被包含到你应用的package中。

这个过程也会产生一个R class文件,这个文件引用了项目中的所有资源。这个为你的代码提供了资源的引用以及设计时候的变量检查。

接下来的部分描述了这些目录中可用的资源类型,以及如何为你的应用创建它们。

资源文件的命名要遵循以下方式:仅使用小写字母、数字、.和下划线_

3-4


Creaing Simple Values

支持的简单值包括stringscolors,dimensions,string或者integer数组。所有的简单值被存储在res/values文件夹的下的XML文件中。

每个XML文件中指定了存储的标签的类型值。如图Listing 3-1显示的XML文件

图 Listing 3-1


上边这个例子中包含了所有的简单值类型。按照约定俗成的方式来说,每种类型的值都会被分成不同的文件存储。例如,res/values/strings.xml文件只是包含string的资源类型定义。

接下来的我们会详细介绍定义simple resource的配置项。

Strings

外部化你的strings帮助你更好的维护你的应用,并且能让国际化更加简单。

String 资源被通过<string>标签引用。如下XML片段所示:

   <string name="stop_message">Stop.</string>

Android支持简单的文本样式,所以你可以使用HTML标签<b><i><u>对你的文本strings去进行加粗,斜体、或者增加下划线,如下XML片段所示:

   <string name="stop_message"><b>Stop.</b></string>

对于String.format方法,你可以使用资源strings作为输入参数。但是,String.format方法不支持上边描述的文本样式。为了将格式化的文本能使用String.format方法,当你创建资源时你不得不去讲HTML标签转换,如下所示:

   <string name="stop_message"><b>Stop</b>. %1$s</string>

在你的代码中,使用Html.fromHTML方法去讲这个转换成一个有样式的字符序列。

   String rString = getString(R.string.stop_message);

   String fString = String.format(rString, "Collaborate and listen.");

   CharSequence styledString = Html.fromHtml(fString);

Colors

使用<color>标签去定义一个新的color资源。通过使用#符号去指定一个color的值,然后就是将红、绿、蓝值进行组合来描述具体的颜色:

·    #RGB

·    #RRGGBB

·    #ARGB

·    #AARRGGBB

下边的例子展示了如何去指定一个蓝色和渐变绿色的值:

   <color name="opaque_blue">#00F</color>

   <color name="transparent_green">#7700FF00</color>

Dimensions

Dimensions(尺寸)是最常见的被引用的资源,一般他们在创建布局的时候用来指定边框的像素和字体高度。

我们使用<dimen>标签去声明一个dimension资源,指定dimension尺寸值,同时指明一个尺寸的单位值:

· px (screen pixels)

· in (physical inches)

· pt (physical points)

· mm (physical millimeters)

· dp (density-independent pixels relative to a 160-dpi screen)

· sp (scale-independent pixels)

这些可选项允许你定义不同的尺寸,而不是定义成绝对的大小,我们针对不同的硬件和屏幕可以进行量体裁衣了。

下边的XML片段展示了如何指定一个大的字体和一个标准边框的尺寸值

   <dimen name="standard_border">5dp</dimen>

   <dimen name="large_font_size">16sp</dimen>

Styles and Themes

Style资源通过你为Views指定的属性值保持应用的界面和感受。最常见使用themesstyles的方式就是存储颜色和字体。

你可以简单的更改你应用的界面,只需要在你项目manifest中简单的指定一个不同的styletheme

通过一个包含name属性的<style>标签去创建一个style,同时他的内部可以包含一个或者多个<item>标签。每个item标签包含一个name属性用来指定被定义的属性。标签本身应该包含值,如下代码所示:

   <?xml version="1.0" encoding="utf-8"?>

      <resources>

      <style name="StyleName">

         <item name="attributeName">value</item>

      </style>

   </resources>

Styles支持集成的方式,这个可以通过<style>标签的parent属性指定。这让他更加容易的创建简单的变量。

下边的例子展示了两个styles能被一个theme使用:一个基本的style设置了几个文本属性,另外一个style修改了那个基本的style,并使其定义的字体变小。

   <?xml version="1.0" encoding="utf-8"?>

   <resources>

      <style name="BaseText">

         <item name="android:textSize">14sp</item>

         <item name="android:textColor">#111</item>

      </style>

      <style name="SmallText" parent="BaseText">

         <item name="android:textSize">8sp</item>

      </style>

   </resources>

Drawables

Drawable 资源包括bitmapsNinePatchPNG)图片。他也包含一些更加复杂的组合Drawables,例如LevelListDrawablesStateListDrawables,这些能在XML文件中定义。

所有的Drawables被存在独立的文件夹res/drawable中,对于一个Drawable资源的标识是一个没有拓展的小写文件名。

注意:最好的bitmap资源是PNG,虽然GPGGIF文件也会被支持。

Layout

Layout资源让你的表现层松耦合,我们可以在XML中定义你的布局而不是在代码中定义。

最常见layout用法是为一个Activity定义一个用户接口。一旦在XML中定义了,布局会在Activity中通过SetContentView 

使用,通常这个被包含在onCreate方法中。你也可以从其他的layout资源中引用layouts,例如为每行引用一个List View 

layout

使用layout去创建你的展示界面在android中是一个最佳实践。代码与layout松耦合能让你为不同的硬件配置创建最优的

layout,例如不同的屏幕大小、表现方式、键盘和触摸屏等等。

每个布局的定义被存储在一个单独的文件中,包含了一个layout,存放在res/layout 文件夹中。文件名会变成这个资源

的唯一标识。

针对layout容器和View的完整解释会在下个章节阐述,图Listing 3-2展示了使用项目向导创建的布局信息。他使用了一

个线性布局作为布局容器,并且包含了一个文本视图展示了“Hello World”的问候信息。

图 Listing 3-2


Animations

Android支持两种类型的动画。Tweened 动画可以被用来旋转,移动、拉伸和隐藏;或者你可以创建帧动画去展示一系列的Drawable图片。深度使用创建和应用动画将会在第15张详细说明。

把动画定义为外部资源可以让你在多个地方重用相同系列动画,并且给你提供了一个基于不同设备和定位去显示不同的动画。

Tweened Animations

每个tweened动画都被以单独文件形式存储在项目的res/anmi文件夹下。就像其他布局和Drawable资源,动画文件的名字会被用作资源的唯一标识。

动画可以被定义为渐变、所见、移动或者旋转。

表 Table 3-1 展示了每种动画类型支持的有效属性,属性值

你可以使用set标签创建一个组合动画。一个动画集合包含一个或者多个动画转换,同时支持多个其他标签和属性供我们设定动画如何去运行。

下边列表展示了一些可用的标签集合。

  duration:动画运行时间

  startOffset:动画开始前延迟播放时间

  fillBefore:设定为true的时,在动画开始前使用转换

  fillAfter:设定为true时,在动画播放完毕后使用转换

  Interpolator:设定动画播放速度。第十五章的时候我们将深入探讨。需要说明的是,使用系统动画资源要通过android:anim/interpolatorName

表 table 3-1:动画类型属性:


注意:如果你设定startOffset标签,一个集合中所有的动画效果都会一起执行。

下边的例子展示了一个动画设定,当他缩小或者渐变退出的时候旋转360度。

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android"

android:interpolator="@android:anim/accelerate_interpolator">

<rotate

android:fromDegrees="0"

android:toDegrees="360"

android:pivotX="50%"

android:pivotY="50%"

android:startOffset="500"

android:duration="1000" />

<scale

android:fromXScale="1.0"

android:toXScale="0.0"

android:fromYScale="1.0"

android:toYScale="0.0"

android:pivotX="50%"

android:pivotY="50%"

android:startOffset="500"

android:duration="500" />

<alpha

android:fromAlpha="1.0"

android:toAlpha="0.0"

android:startOffset="500"

android:duration="500" />

</set>

Frame-by-Frame Animations

帧动画允许你创建一系列的Drawables,在View的背景中每个都会展示一段时间。

因为帧动画展现的是存储在res/drawable文件中的动画Drawables,而不是tweened 动画,使用它们的文件名作为资源ID

下边的XML片段展示了一个简单的循环显示一系列的bitmap资源动画,并且每个展示0.5秒。为了使用这个片段,你需要创建新的图片资源rocket1rocket3.

<animation-list

xmlns:android="http://schemas.android.com/apk/res/android"

android:oneshot="false">

   <item android:drawable="@drawable/rocket1" android:duration="500" />

   <item android:drawable="@drawable/rocket2" android:duration="500" />

   <item android:drawable="@drawable/rocket3" android:duration="500" />

</animation-list>

Menus

创建menu(菜单)资源会进一步分离你的展现层和代码。这样你在设计菜单的布局的时候可以使用XML而不是直接在代码中构造它们。

Menu资源能被用来定义你应用中的Activitycontext menus,同时你也可以在代码中构造menu项。一旦你在XML定义了,通过MenuInflatorinflate方法menu会被展示到你的应用中,这个一般都在onCreateOptionsMenu方法中调用。在第四章中你可以看到menus的深入探讨。

每个menu的定义都在res/menu文件中以独立文件的方式存储,每个里边都包含一个menu。文件名会作为资源的标识。使用XML去定义你的menusAndroid中是一个最佳实践。

一个全方位的阐述menu配置项的说明在下章中被说明,但是 图Listing 3-3 展示一个简单的menu例子。

图 Listing 3-3


1.1.2 使用资源

当你创建完资源的同时,Android提供了一些系统资源,这些你都能在应用中使用。这些资源可以被直接在应用中使用,也可以在其他资源中北引用。

接下来你将会了解到如何为不同的语言、地区以及硬件定义不同的资源值。有一点你需要知道,使用资源的时候你不能指定某个特定的版本。Android会基于当前硬件和设备的设置去自动的为给定的资源id选择最合适的值。

在代码中使用资源

在代码中访问资源可以使用静态类R classR是一个基于你的外部资源的衍生类,当你项目编译的时候被创建。R class针对你已经定义的每种类型的资源对应包含一个静态子类。例如,新创建的项目默认包含R.string R.drawable子类。

注意:如果你在eclipse中使用ADT插件,当你做任何外部资源的更改时,R  class将会自动的被创建。如果你没有使用插件,只是使用AAPT工具去编译你的项目并产生R classR是一个编译产生的类,所以不要做任何手工的修改,否则当资源文件修改后,他们就会丢失。

每个R class暴露的子类资源都被认为是变量,变量名和资源标识一一对应。例如:R.string.app_name 或者R.drawable.icon

这些变量的值是对资源表中的资源位置的一个引用,不是资源实例的本身。

在一些构造函数或者方法中,例如setContentView,接收一些资源标识,你可以在资源变量中传递,如下代码所示:

// Inflate a layout resource.

setContentView(R.layout.main);

// Display a transient dialog box that displays the

// error message string resource.

Toast.makeText(this, R.string.app_error, Toast.LENGTH_LONG).show();

当你需要资源实例本身,你需要使用helper方法到资源表中抽取他们。在你的应用中,资源表被作为一个Resources class展现。

因为这些方法的展现基于应用的资源表,这些帮助方法不能是静态的。在你的应用上下文使用getResources方法去访问你应用的资源实例。代码如下:

Resources myResources = getResources();

Resources 类包含每个可用资源类型的的getter方法,并且你可以通过传递resource ID获取。下边代码展示了用helper方法去返回一个指定的资源值。

Resources myResources = getResources();

CharSequence styledText = myResources.getText(R.string.stop_message);

Drawable icon = myResources.getDrawable(R.drawable.app_icon);

int opaqueBlue = myResources.getColor(R.color.opaque_blue);

float borderWidth = myResources.getDimension(R.dimen.standard_border);

Animation tranOut;

tranOut = AnimationUtils.loadAnimation(this, R.anim.spin_shrink_fade);

String[] stringArray;

stringArray = myResources.getStringArray(R.array.string_array);

int[] intArray = myResources.getIntArray(R.array.integer_array);

帧动画资源被设定为AnimationResources。你可以使用getDrawable获取并且对返回值进行转换。如下代码所示:

AnimationDrawable rocket;

rocket = (AnimationDrawable)myResources.getDrawable(R.drawable.frame_by_frame);

在资源中内部引用资源

你也可以将资源引用作为属性值放到其他的XML资源中

这个针对layouts布局和styles风格样式十分有用,允许你针对主题和本地string以及图片创建特定的变量。他也是用来解决不同的屏幕大小和分辨率的最有效的方法。

引用其他package资源文件中的资源需要使用@标识,如下代码所示。

attribute="@[packagename:]resourcetype/resourceidentifier"

备注:Android会假定你正使用同package中的资源,如果你需要使用其他package中的资源,你仅仅需要设定全路径名称。图Listing3-4 展示了一个使用colordimensionstring资源的布局器。

Listing 3-4


使用系统资源

本地原生的Android应用有很多外部化资源,为你提供了stringsimages,动画,styleslayouts在你的应用中使用。

在代码中访问系统的资源与访问你自己的资源类似。不同的是,你使用原生的Android资源classes是使用android.R类,而不是应用的引用类R。下边的代码展示了应用上下文中使用getString方法从系统资源中获取一个错误信息提示。

CharSequence httpError = getString(android.R.string.httpErrorBadUrl);

在XML文件中访问系统资源需要指定Android作为package的名字。如下XML片段所示:

<EditText

android:id="@+id/myEditText"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="@android:string/httpErrorBadUrl"

android:textColor="@android:color/darker_gray"

/>

在当前theme中使用style

使用themes是一个较好的方法去保证应用UI的流畅。相对于完全定义每一个styleAndroid提供了一个快捷方式让你去使用当前应用的themestyles

要这样使用需要使用 ?android:而不是标识作为你想使用资源的前缀。下边的例子展示了一个使用当前theme的文本颜色而不是一个外部资源的文本颜色。

<EditText

android:id="@+id/myEditText"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="@string/stop_message"

android:textColor="?android:textColor"

/>

这个技术让你创建的styles会随着当前theme的改变而变化,不需要你去修改每个style  resource


1.1.3 资源例子作业

1.1.4 为不同的语言和硬件创建资源

外部化资源的一个最令人信服的理由是Android的动态资源选择机制。

使用下边描述的目录结构,你可以为不同的语言,位置和硬件配置创建不同的资源值。Android将会在运行时动态选择这些值。

你可以在res文件下通过使用平行的目录结构选择不同的资源值。

一个(-)连字符被用来区分你提供指定的相关状态信息。

下边文件夹中的目录结构展示了默认的string值,法语和加拿大法语的变量值的存放方式:

Project/

   res/

      values/

         strings.xml

      values-fr/

         strings.xml

      values-fr-rCA/

         strings.xml

下边的列表提供了你可以使用定制的相关资源值

Mobile Country Code and Mobile Network Code (MCC/MNC):国家和当前设备中的SIM卡的可选择网络。MCC可以通过mcc 加上三个国家代码指定。MNC可以通过mcc加上两个或者三个国家码指定(例如:mcc234-mnc20 or mcc310)。你可以到如下的网站找到MCC/MNC的编码:http://en.wikipedia.org/wiki/Mobile_Network_Code

· Language and Region:语言可以通过ISO639-1 标准的两个小写字母,配合一个小写的r加上ISO3166-1-ALPHA-2语言编码

· 指定地区(例如:en,en-rUS,或者en-rGB.

· Screen Size:可以选择small(HVGA还小)medium(大于HVGA小于VGA),或者large(比VGA大)。

· Screen Width/Length:特意为宽屏资源设计指定long或者notlong(例如:WVGA longQVGAnotlong)。

· Screen Width/Length:可以选择portportrait,land(landscape),或者square(square)

· Screen Pixel Density:以点计算每英寸的像素比重(dpi)。最好的方法是使用ldpi,mdpi或者hdpi去指定low120dpi),medium160dpi),或者high240dpi)。你也可以针对位图资源指定nodpi,这样是在你不想指定支持的准确像素。不像其他的资源类型,Android不需要针对资源的一个精准匹配。当选择合适的文件夹,他就会自动的选择最近的去匹配设备的像素和自动的拓展Drawables的结果。

· Touchscreen Type:可以选择 notouch,stylus,finger

· Keyboard Availability:可以选择 keysexposed keyshidden,keyssoft

· Keyboard Input Type:可以选择 nokeys,qwerty,12key

· UI Navigation Type:可以选择nonav,dpad,trackball,whell

你可以为任何资源类型指定多个值,通过一个连接符(-)进行分割。任何组合都是可以被支持的,但是需要有一个先后

顺序,一次只能有一个被使用。

下边展示了针对不同的Drawable资源,有效和无效的目录名

· Valid:

drawable-en-rUS

drawable-en-keyshidden

drawable-long-land-notouch-nokeys

· Invalid:

drawable-rUS-en (out of order)

drawable-rUS-rUK (multiple values for a single qualifier)

Android在运行时获取资源的时候,他会找到当前可用方法中最匹配的那个。当有一大串的可选资源存在的时候,他会选择一个最匹配的。如果两个资源的匹配度相同,他会基于匹配的顺序选择。

注意:如果给定的设备上没选中的资源,你的应用访问资源的时候会抛出异常。为了避免这个,最好的方式就是永远为每个资源指定默认值。

1.1.5 运行时配置变更

Android是可以通过终止和重启每个应用去加载资源值在运行时更改语言、位置和硬件配置。

默认设定的行为模式不会总是最方便和最想要的,特别当一些配置变化的时候(例如屏幕分辨率和键盘是否可用)都会发生,就像用户旋转设备或者推出键盘。你需要定制你的应用去感应、检测这些改变,并且做出反馈。

为了侦听一个Activity在运行时配置的改变,我们可以通过增加一个android:configChange属性到他们的manifest节点,指定配置改变时你想做的处理。

下边列表描述了配置改变时候你能做的指定:

· orientation:当屏幕在横竖做旋转的时候

· keyboardHidden:键盘被展示或者隐藏

· fontScale:用户改变了字体大小

· locale:用户改变了语言设置

· keyboard:键盘类型改变了。例如,电话可以有一个12键的快捷键,也可以变成全键盘

· touchscreen or navigation:键盘类型或者导航方式发生变化。这些事情都不会正常发生。

一定情况下,多个事件会同时被触发。例如,当用户推开键盘,很多设备会触发keyboardHiddenorientation 事件。

你可以选择多个你想处理的时间通过(|)符号进行分割。

Listing 3-5 展示了一个activity代码声明了他要处理的一些动作,当屏幕旋转或者键盘可见的时候被触发。

图 Listing 3-5


增加一个android:configChanges属性禁止特定的配置在重启后变更,而不是在Activity中触发onConfigurationChanged方法。通过覆盖这个方法去处理配置的改变,通过传进来的Configuration对象去确认新的配置值,如图Listing 3-6中显示的那样。确保回调父类的方法重新加载Activity的资源值,以免他们改变。

Listing 3-6


onConfigurattionChanged被调用,Activity资源变量值已经更新为最新值,所以他们可以被安全的使用。

任何你在应用中没声明的配置改变都会导致你的Activity去重启,而不是去调用onConfigurationChanged方法。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值