原文地址:App Resources
它不仅仅是一个好的app的一段代码,Resources是一个额外的文件,它是静态写在程序中的,例如bitmaps、layout definitions、user interface strings、animation instructions等等。
一、Resources Overview 概览
通常我们应该将程序中的图片或者string从代码中提取出来然后写在Resources中,因为这样有助于我们管理这些资源,也有助于app支持各种不同的语言、屏幕大小,可以支持各种各样的配置。
那为了实现这个功能,通常我们将这些Resources都组织值res/的文件夹下,然后再根据这个下面的一些文件夹进行设置区分。
对于任意的Resources你都可以为它设定默认值或者是多选项:
Default Resources(默认值):不在乎设备配置,或者当没有可选项的时候用它。
Alternative Resources(多选项):根据不同的设备配置自动获取某项。你要通过文件名来对不同的选项设置不同的匹配项。
举例:
如果只有一个默认选项,那就只能像上面的这个图了。
那如果你有多种选项来适配不同的设备时,效果就是酱紫,哈。
点击打开链接
二、Providing Resources 资源类型
这里讲一下Resources提供了哪些资源类型。我们应该将不同类型的Resources放在res/下的不同目录中。就像这样:
MyProject/ src/ MyActivity.java res/ drawable/ icon.png layout/ main.xml info.xml values/ strings.xml下面的Table1展示了在res/目录下支持的目录名称:
注意点一:不要直接将资源文件 resource files直接放到res/文件夹下,会造成编译错误。
上表中定义的子文件夹都属于默认值Default。但是不同的设备要用不同类型的资源。所以你还是要弄多选项的。
那关于多选项的名称的创建规则是这样的:
注意点二:当跟多个
举例:
res/ drawable/ icon.png background.png drawable-hdpi/ icon.png background.png
下面Table2给出了可用的限定符:
MCC and MNC:手机国家地区编码
Language and region:语言和地区
Layout Direction:布局方向?
smallestWidth:屏幕大小
Available width:最小可接受的屏幕宽度
Available height:最小可接受的屏幕高度
Screen size:屏幕大小
Screen aspect:屏幕长短
Screen orientation:屏幕方向
UI mode:UI模式
Night mode:夜间模式
Screen pixel density(dpi):屏幕分辨率
Touchscreen type:触屏类型
Keyboard available:键盘是否可用
Primary text input method:初始输入
Navigation key available:导航
Primary nontouch navigation method:导航
Platform Version(API level):平台版本
限定符使用规则:
1、按Table2中的顺序使用多个限定符:
drawable-en-rUS-land
applies to US-English devices in landscape orientation.
2、按顺序!
3、不可以相互嵌套,例如:res/drawable/drawable-en/
4、不区分大小写的。
5、如果统一资源属于两个限定符中,那就把这个资源复制到两个文件夹下。同一类型的限定符不可以同时使用,例如:drawable-rES-rFR/,但是!你也没有必要把资源复制两份,你可以使用alias resources!
所有的匹配都是Android自动进行的。
创建alias resources:
注意点一:并不是所有的resources都适用于这个功能,例如:animation、menu、raw、unspecified resources in xml/。
先举例吧:
To create an alias to an existing drawable, use the
element. For example:
xml version="1.0" encoding="utf-8"?>假设我们有一个图片icon.png,还需要放在xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/icon_ca" />
res/drawable-en-rCA/
and res/drawable-fr-rCA/。然后我们可以把它的名字保存成例如icon_ca.png,放在默认的res/drawable/文件下。然后再创建一个icon.xml文件分别放在res/drawable-en-rCA/
and res/drawable-fr-rCA/中,这个icon.xml中通过bitmap的src属性引用了icon_ca.png,这样你就可以直接通过icon.xml来使用啦。这样当我们引用的时候要写R.drawable.icon!!!!
再举一个例子:
To create an alias to an existing layout, use the
element, wrapped in a
. For example:
xml version="1.0" encoding="utf-8"?>如果我们把上面的文件存为main.xml,那么使用的时候就写R.layout.main。layout="@layout/main_ltr"/>
再举个例子:
To create an alias to an existing string, simply use the resource ID of the desired string as the value for the new string. For example:
xml version="1.0" encoding="utf-8"?>这样就可以用R.string.hi来代替R.string.hello。name="hello">Hello name="hi">@string/hello
xml version="1.0" encoding="utf-8"?>name="yellow">#f00 name="highlight">@color/red
Android系统要根据资源来得到最佳匹配:
注意点一:如果你的应用适应多种限定,那你一定要提供一个默认资源保证应用正确运行。否则可能没有了
注意点二:如果你的应用适应横屏和竖屏,不要这样写: layout-land/
for landscape andlayout-port/
for portrait。而要这样写:layout/
for landscape and layout-port/
for portrait。
注意点三:默认选项还有一个重要意义就是版本升级后你可能没有新的限定资源。
有一个例外:当你的minSdkVersion是4以上的时候,你不需要默认的drawable resources来面对不同分辨率限定符。Android会自动去匹配最佳的。不过为了显示效果,你还是提供不同分辨率的图片好了。
Android是如何寻找最佳匹配资源的呢?
按照Table2中的限定符,一个一个的对比。在匹配过程中,分辨率是最后才考虑的。正如在Table2中它放在最后。
在屏幕大小screen size限定中,当没有直接匹配时,系统会选择一个比当前屏幕更小的屏幕。当如果只有更大的屏幕时,系统不会采用它,你的应用将会崩溃。
Accessing Resources
三、Accessing Resources 访问资源
应用程序编译后,aapt会自动生成R.java,它里面包含所有的资源ID。
由resource type(string、drawable、layout)和resource name组成。
访问方法:
1、在代码中这样写:R.string.hello。
2、在XML文件中这样写:@string/hello
具体介绍在代码中访问资源:
这样直接使用:
ImageView imageView = (ImageView) findViewById(R.id.myimageview); imageView.setImageResource(R.drawable.myimage);或者是通过Resources中的方法来检索,通过Context.getResources()。
语法Syntax:
[.]R. .
是你的资源所在的包名,如果在同一个包下,就不用写了。
资源名称
举例吧:
// Load a background for the current screen from a drawable resource注意点一:永远不要去修改R.java文件。getWindow()
.setBackgroundDrawableResource
(R.drawable.my_background_image) ; // Set the Activity title by getting a string from the Resources object, because // this method requires a CharSequence rather than a resource IDgetWindow()
.setTitle
(getResources().getText
(R.string.main_title)); // Load a custom layout for the current screensetContentView
(R.layout.main_screen); // Set a slide in animation by getting an Animation from the Resources object mFlipper.setInAnimation
(AnimationUtils.loadAnimation(this, R.anim.hyperspace_in)); // Set the text on a TextView object using a resource ID TextView msgTextView = (TextView) findViewById(R.id.msg); msgTextView.setText
(R.string.hello_message);
具体介绍在XML中访问资源:
语法Syntax:
@[举例吧::] /
xml version="1.0" encoding="utf-8"?>name="opaque_red">#f00 name="hello">Hello!
xml version="1.0" encoding="utf-8"?>如果引用的是系统资源,那就需要加上包名:xmlns:android="http://schemas.android.com/apk/res/android" android:layo 18db ut_width="fill_parent" android:layout_height="fill_parent" android:textColor="@color/opaque_red" android:text="@string/hello" />
xml version="1.0" encoding="utf-8"?>注意点一:应该使用string资源,这样你的应用程序就可以适应于各种语言。xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:textColor="@android:color/secondary_text_dark" android:text="@string/hello" />
学会用alias resources:
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/other_drawable" />
引用style attributes样式属性:
style attribute资源就是当前应用的主题里的属性。通过引用style attribute可以帮助我们使用自定义的属性。主要强调的是:自定义!!!当前主题!!!
语法Syntax:把@换成?
?[<package_name>:][<resource_type>/]<resource_name>举例:
id="text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="?android:textColorSecondary"
android:text="@string/hello_world" />
Here, the
android:textColor
attribute specifies the name of a style attribute in the current theme. Android now uses the value applied to the
android:textColorSecondary
style attribute as the value for
android:textColor
in this widget. Because the system resource tool knows that an attribute resource is expected in this context, you do not need to explicitly state the type (which would be
?android:attr/textColorSecondary
)—you can exclude the
attr
type.
引用平台资源Platform Resources:
Android包含了很多标准资源,例如styles、themes and layouts。为了引用这些资源,确保你你的资源引用了android package name。
setListAdapter
(newArrayAdapter
<String>(this, android.R.layout.simple_list_item_1, myarray));
simple_list_item_1
就是定义子啊ListView中的一个layout resource。
四、Handing Runtime Changes 随运行时间改变处理
当设备参数(screen orientation、keyboard availability、language、接电话)在运行时发生变化时,Android就会重启activity(先onDestroy(),然后onCreate()),然后选择相对应的可选资源。
因为了重启activity,因此保存上一次的运行状态很重要。Android是通过在destroys前调用onSaveInstanceState()在保存程序状态,然后在重启时调用onCreate()或者onRestoreInstanceState()。
因为保存重启会带来较差的用户体验,我们可以使用下面的这两种方式:
1、在配置发生变化的时候保存一个对象。
让系统去重启activity。
2、你自己来处理配置变化。
当配置变化时组织系统重启你的activity,而是根据需求回调来手动的更新你的activity。
具体介绍:在配置发生变化的时候保存一个对象
重启一个活动需要恢复各种数据,比如说网络连接、密集操作,带来差的用户体验。而且也可能不能够完全重建。系统会通过回调onSaveInstanceState(),它里面有用Bundle,但是它不适合于存储大量的数据内容,而且bundle存储的数据必须要序列化。当然系统也可以使用另一种方式那就是使用Fragment碎片。
当Android系统由于配置变化要关闭你的activity时,你的activity中标记了去保存数据的fragments却不会被销毁。你可以给你的activity添加这样的Fragment来保存数据对象。
方法呢就是:
Fragment
class and declare references to your stateful objects.setRetainInstance(boolean)
when the fragment is created.FragmentManager
to retrieve the fragment when the activity is restarted.public class RetainedFragment extends Fragment { // data object we want to retain private MyDataObject data; // this method is only called once for this fragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // retain this fragment setRetainInstance(true); } public void setData(MyDataObject data) { this.data = data; } public MyDataObject getData() { return data; } }注意点一:当你想要保存任意对象的时候,确保这个对象和Activity无关联,例如a Drawable、an Adapter、a View 或其他任何和Context有关联的对象。不然就会泄漏所有之前的view和resource。这里泄漏的含义是说它们无法被回收,浪费内存。
然后通过Fragmentmanager将这个fragment添加到Activity中。
public class MyActivity extends Activity { private RetainedFragment dataFragment; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // find the retained fragment on activity restarts FragmentManager fm = getFragmentManager(); dataFragment = (DataFragment) fm.findFragmentByTag(“data”); // create the fragment and data the first time if (dataFragment == null) { // add the fragment dataFragment = new DataFragment(); fm.beginTransaction().add(dataFragment, “data”).commit(); // load the data from the web dataFragment.setData(loadMyData()); } // the data is available in dataFragment.getData() ... } @Override public void onDestroy() { super.onDestroy(); // store the data in the fragment dataFragment.setData(collectMyLoadedData()); } }
具体介绍:你自己来处理配置变化
如果你的应用在特定配置变化情况下不需要更新资源那么手动的组织活动重启,然后自己来处理。
注意点一:手动处理是比较麻烦的,因为系统不会自动的为你执行手动处理。这个技术需要你去做一系列的操作,并且在很多的应用中并不建议用手动处理。
那为了声明你要手动处理,你需要去修改Manifest文件中的android:configChanges
这个属性。这是属性可选的值有:
最常用的值呢就是"orientation","keyboardHidden"。可以同时声明多个用 | 来分割。有一个满足条件就不重启。然后会调用onConfigurationChanged(),在这个函数中你可以根据配置的变化手动更新你activity中的资源。
This method is passed a Configuration
object that specifies the new device configuratio 1ac5 n. By reading fields in the Configuration
, you can determine the new configuration and make appropriate changes by updating the resources used in your interface.
android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
注意点二:当你的API level在13以上时,要在config中加入“screenSize”这个值,但如果是12以下的话,就随便啦。
下面这个例子实现了检测当前设备的orientation:
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); } }这个Configuration object代表了所有当前的配置,不仅仅是改变了的那些配置。大多数的时候你不需要精确的知道所有改变的配置,仅仅需要简单的手动去设置那些由于某些配置改变而引起的资源的改变。
比如说,因为Resources对象被更新,你可以通过setImageResource()重设所有的ImageViews。
注意点三:来自Configuration的值都是整数,在Configuration类中匹配特定的常数。具体的对应值去查啦。
注意四点:当你手动处理配置变化时,你必须要重设所有你提供了的可选项。
当配置变化时,如果你不需要修改任何资源,那你可以不用去实现onConfigurationChanged()。这里你就仅仅是阻止了活动的重启。但是最好还是不要这样用啦,还是安心重启好了。
Localizing with Resources
五、Localizing with Resources 本地化资源
没看懂啊
六、Resource Types
博客链接:Animation