安卓发展到现在,N previw都已经在路上了。市面上的安卓机也是成千上百万,你用你的Ice-cream Sandwich,我用我的marshmallow;你用你的7寸两手捧4K超大屏,我用我的4.5寸单手神器;You Speak English,我说普通话...谷歌孩子这么多,还是要兼顾下的,这样才能尽可能的占领更多客户嘛,所以我们的app要去尝试兼容不同大小、分辨率、语言、地区的设备。
支持不同语言
之前提到的不要把字符串hard code在代码里,好处就体现出来了:如果我们有一个字符串是hard code的,那么无论在什么设备上使用,它显示的都是一样的内容,而我们有可能希望在不同的情景下显示不同内容,例如用户的系统语言是英文,我们就显示英文;用户系统语言是中文繁体,我们就显示中文繁体。
所以,将app中的字符串抽出来放在strings.xml中是非常有意义的。
创建区域路径及字符串文件
安卓系统会根据在运行时的设备区域设定来载入对应的资源。举个例子,比如说我们要支持香港中文(繁体)的显示,那么我们就需要在res路径下再建立一个values文件夹,命名是用values加连字号-加ISO语言代码(两字母的ISO 639-1语言代码,后面可选跟随两字母的ISO 3166-1-alpha-2区域代码,区域代码前面固定添加一个小写的r)。更多信息可以参考谷歌Providing Resources。
什么限定符都不带的values文件夹是作为缺省的默认值使用的。
在AS的导航栏中右键点击res,选择New -> Android resource directory:
然后,在Resource type中选择values,可以看到AS其实已经帮我们整合好了可选的修饰词:
我们在Available qualifiers中选择Locale区域,之后搜索找到中文,接下来选择区域,这里我分两次分别选择了大陆和香港。
点击OK会即会生成新的value文件夹,大陆地区对应的是values-zh-rCN,香港对应的文件夹是values-zh-rHK。
接下来我又建立了一个values文件夹,区域选择的是日本,生成的是values-ja。
然后分别在这三个文件夹中建立strings.xml文件,加上缺省的values文件夹中的这个文件,我们总共有4个了。
接下来分别在各自的xml文件中写入与区域对应语言的字符串,对于同一个字符串名字,在不同xml文件中是一样的,区别只是他们的值(用百度翻译的日文,原谅我的无知):
// values\strings.xml
<resources>
<string name="app_name">Support Different Language</string>
<string name="hello_world">Hello World!</string>
<string name="send_btn">SEND</string>
</resources>
// values-zh-rCN\strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">支持不同语言</string>
<string name="hello_world">你好!世界!</string>
<string name="send_btn">发送</string>
</resources>
// values-zh-rHK\strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">支持不同語言</string>
<string name="hello_world">你好!世界!我是香港繁體</string>
<string name="send_btn">發送</string>
</resources>
// values-ja\strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">違う言葉を支持する</string>
<string name="hello_world">こんにちは!世界!</string>
<string name="send_btn">送信</string>
</resources>
编译,真机运行,将系统设置成不同的语言,可以看到:
使用字符串资源
我们可以通过string标签中的name字段对这个字符串进行引用。在不同文件中所不同的是,写法可能不同:
在源代码中引用字符串的格式是R.string.<string_name>,具体如下:
// Get a string resource from your app's Resources
String hello = getResources().getString(R.string.hello_world);
// Or supply a string resource to a method that requires a string
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);
在XML文件中引用字符串的格式是@string/<string_name>,具体如下:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
支持不同屏幕
创建不同的布局
与区域语言同理,在res上邮件选择New -> Android resource directory,然后在resource type中选择layout,限定符选择orientation中的land(由于本人没有屏幕差距较大的安卓设备,所以就以竖向横向为例了),也就是横向。
layout-land\文件夹建好后我们在其中添加一个与layout\文件夹下面的activity_main.xml名字一模一样的布局文件,唯一的区别就是将最外面的布局背景设置为橙色。
编译,真机运行,将屏幕从竖直变成水平,效果就出来了:
创建不同位图
对于app中的位图资源,我们最好也能够提供如下四种分辨率:low、medium、high以及extra-high。这有助于提高我们在不同屏幕上的图像表现。
在原始的向量格式的资源中按如下尺寸比例生成上面这些图片资源:
1. xhdpi:2.0
2. hdpi:1.5
3. mdpi:1.0(基准)
4. ldpi:0.75
举个例子,如果你为xhdpi的设备提供的图片分辨率是200x200的,那么对应给hdpi的同一图片分辨率就应该是150x150,mdpi应该是100x100,ldpi为75x75。
对于文件存放的路径,也与前面相似,都是放在对应分辨率的drawable-<density>\路径下,例如,xhdpi的文件放在drawable-xhdpi\路径下。
另外值得注意的是,低分辨率(ldpi)的资源并不是一定需要的,因为系统会将hdpi的资源尺寸减半来适应低分辨率的屏幕。
图标设计方面可以参考,Iconography design guide。
支持不同平台版本
新的安卓版本总是会给我们提供很多更新更精彩的API,Android Dashboard上面的平台版本也显示了Google Play Store中活动的设备不同版本所占的比例。
为了在不同的Android版本中提供更好的特性和功能,我们可以在app中使用Android Support Library,它允许我们在旧的安卓版本上使用一些新版本中的API。
指明最小和目标API级别
AndroidManifest.xml文件中描述了app的最小API级别以及目标API级别(和我们创建项目时候的值是一致的),定义使用的是use-sdk这个标签。
举个例子:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wenhe.supportdifferentlanguage" >
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23" />
//...
</manifest>
在运行时检查系统版本
安卓在Build常量类中为每个安卓版本都提供了一个唯一的代码。通过使用这些代码来进行判断,仅当当前系统API满足条件时才执行某些代码。
举个例子:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView txtSDK = (TextView) findViewById(R.id.txtSDK);
if(Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
txtSDK.setText("Your System is the latest M");
}
else {
txtSDK.setText("Your System is not M");
}
}
}
编译好之后分别在系统为6.0和4.2.2的两台设备上运行,效果如下:
值得注意的是,在解析XML资源的时候,安卓会忽略当前设备不支持的XML属性,所以放心大胆地使用XML吧。
使用平台的样式和主题
<activity android:theme="@android:style/Theme.Translucent">
<activity android:theme="@style/CustomTheme">
<application android:theme="@style/AppTheme" >