Android Training学习笔记之适配不同的设备

Posted createchance

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Training学习笔记之适配不同的设备相关的知识,希望对你有一定的参考价值。

android是一个开源的开放的操作系统,世界上的任何人都可以基于这个系统进行适合自己的定制活动。Android的这样一个特点使得android世界的碎片化很严重,形形色色的android设备太多太多。这就给app开发带来了不小的困难,保证app在不同的设备上的使用体验是一致的是每一个开发者必须考虑,但是很头疼的问题。Google在这块也做了很多的工作,尤其是在最新的android 6.0中,多设备的支持和自适应做的已经非常好了。要想让你的app能够利用google提供的优良自适应特性,你必须要遵守一些google的基本规范。google在training中给出了他的规范:
https://developer.android.com/training/basics/supporting-devices/index.html
这个规范一共分为3个部分:

  1. 支持不同的语言
  2. 支持不同屏幕的设备
  3. 支持不同系统版本的设备

接下来我们就简单学习一下google的基本规范。

1. 支持不同的语言

Android作为一个全球化的操作系统,android会运行在世界上任何一个国家,那么android的用户所使用的语言就是非常多样的。为了支持不同国家的语言,android提供了string resource机制,具体的做法就是:你应该在你的项目源码目录下的res目录(也就是你的app的resource目录)中,新建上众多这样格式的目录:

values-<ISO 639-1 locale codes>

然后在这个目录下面新建名为strings.xml的文件,这个文件中所有的tag都是以string开始,然后指定一个名字,最后指定一个对应的值:

<string name="app_name">HelloWorld</string>

这里需要说明一下,上面提到的ISO 639-1 locale codes是国际之间关于国家地区语言代码的ISO全球统一规范,当然android就是遵守这个的。关于ISO 639-1 locale codes规范的简介可以查看维基百科的介绍:
https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
全面的介绍可以查看ISO官网的spec:
http://www.iso.org/iso/home/standards/language_codes.htm
如果你的app支持多国语言的话,那么你的string资源目录可能有点像下面这个样子:

MyProject/
    res/
       values/
           strings.xml
       values-es/
           strings.xml
       values-fr/
           strings.xml

这个例子中支持了默认的语言支持(当找不到支持的语言资源的时候,默认使用这个,一般为英语),西班牙语支持,法语支持。以下是默认语言支持的示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">My Application</string>
    <string name="hello_world">Hello World!</string>
</resources>

这是西班牙语支持示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mi Aplicación</string>
    <string name="hello_world">Hola Mundo!</string>
</resources>

这是法语支持示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mon Application</string>
    <string name="hello_world">Bonjour le monde !</string>
</resources>

是的,就是这么简单,你只要在不同的目录下的strings.xml中定义上相同name不同语言翻译的string后,android系统就可以根据当前系统的语言来决定显示什么文字了!
我们使用这些string资源基本有两种方式:在java代码中使用和在xml等文件中使用,我们先看下再java代码中怎么使用:
来自google的例子

// 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文件中使用:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

2. 支持不同的屏幕

基于android系统的设备是如此之多,从小屏幕的智能手表到日常使用的智能手机,在从汽车上的智能车载到大屏幕的智能电视。屏幕的尺寸和分辨率是我们开发中必须要考虑的一个问题,同语言国际化一样,这块google也有自己的规范。
首先说明一下目前的屏幕尺寸和画面清晰度的分类:
四种屏幕尺寸:small(小), normal(中), large(大), xlarge(超大)
五种屏幕清晰度(细腻度):low(ldpi)低, medium(mdpi)中, high(hdpi)高, extra high(xhdpi)超高, extra extra high(xxhdpi)极高
这里需要额外说明一下,从android 3.2(api level 13)开始,上面4种屏幕尺寸已经不建议使用了,取而代之的是一种根据可用屏幕宽度管理屏幕尺寸的新技术。
通常来讲以上的几种屏幕尺寸和清晰度定义基本如下

更多关于屏幕尺寸和清晰度的信息请参考google的说明:
https://developer.android.com/guide/practices/screens_support.html
在支持屏幕大小的方面,基本有两个问题:一是界面布局,而是图片显示大小。先说说界面布局问题,界面的布局和屏幕的尺寸关系比较大,如一个比较的大的屏幕尺寸和一个小的屏幕尺寸每屏显示的内容肯定不一样,大一点的屏幕可以显示多一点的内容,布局可以更加自由一些,小一点的屏幕显示的内容就比较少,界面元素布局就会相对紧凑一些。和支持多语言一样,在支持多屏幕尺寸上,我们也可以使用不同目录,同样文件名,不同布局内容的策略让android系统根据实际情况决定布局。我们可以在res目录下的layout目录建立这样的目录:

layout-<screen size pattern>

这里的screen size pattern可以是这样的:

land(表示横屏)
large(表示大屏)
large-land(表示大屏横屏)

也就是说你的目录可能会像这个样子:

MyProject/
    res/
        layout/              # default (portrait)
            main.xml
        layout-land/         # landscape
            main.xml
        layout-large/        # large (portrait)
            main.xml
        layout-large-land/   # large landscape
            main.xml

但是,上面也提到了,这个技术在android 3.2之后就不需要使用了,因为android可以使用新技术来定义屏幕尺寸:
https://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLayouts
除了界面布局的问题,还有的就是app中图片的显示问题。不同的分辨率,清晰度去显示同一张图片肯定会有问题的,图片通常会有变形的问题。同样地,这个问题我们可以按照不同目录,同一个文件名的方式来处理这个问题。我们可以在res目录下建立这样的目录:

drawable-<density>

这里的density就是上面提到了几种,因此如果你的app支持不同清晰度的显示,那么你的图片资源目录可能像这样:

MyProject/
    res/
        drawable-xhdpi/
            awesomeimage.png
        drawable-hdpi/
            awesomeimage.png
        drawable-mdpi/
            awesomeimage.png
        drawable-ldpi/
            awesomeimage.png

任何时候你都可以通过@drawable/awesomeimage的方式去使用这个图片,系统会根据当前设备的清晰度自动选择相应的图片显示。另外,不同清晰度之间的比例是这样的:

  1. xhdpi: 2.0
  2. hdpi: 1.5
  3. mdpi: 1.0 (baseline)
  4. ldpi: 0.75

也就是说,xhdpi是mdpi图片尺寸的2倍,如果xhdpi的尺寸是200*200的话,你的mdpi照片就是100*100.同时需要注意的是,低清晰度的图片不是必须的,当你制定了高清晰度的时候,如果设备是低清晰度的话,那么系统会自动按照这个比例缩放你的照片。不过,最好还是指定这样的图片,不然缩放的过程可能增加额外的内存和cpu消耗,并且缩放的效果不一定是你最想要的。图片资源中比较重要的可能就是app的icon的设计了,这个是app的门面,这部分的设计可以参考google的文档:
https://developer.android.com/design/style/iconography.html

3. 支持不同的系统版本

Android是一个快速演变的操作系统,可以看到google的发布更新频率是非常快的,android也在以一个非常快的速度进化着。在快速的版本演化中,有一个问题就是新旧的api版本兼容性的问题。老版本的api的可能早就废弃不用了,新版本的api提供了很好的特性但是很多设备部支持。在创建app的初始,就是决定app的目标平台和最低平台,google的建议是至少覆盖90%的设备用户。
为了让我们的app的能够正常良好地运行在不同版本上,我们需要在AndroidManifest中指定相应的版本问题。我们使用标签制定相应版本,目前可以制定的版本有:
minSdkVersion(最小版本)
targetSdkVersion(目标版本)
maxSdkVersion(最大版本)
其中我们一般制定最小版本和目标版本,最小版本指定你的app必须运行的版本,目标版本指定你的app运行的最理想的版本。这个部分在AndroidManifest中指定方式如下:

<uses-sdk android:minSdkVersion="integer"
          android:targetSdkVersion="integer"
          android:maxSdkVersion="integer" />

每个值都是一个int型的无符号数字,这个数字是android的api level。关于android的api level可以参考下面这个表格(来自google)

我们要填写的就是这表格中的API level中的数字。更多信息,参考:
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
为了获得更加灵活的操作方式,我们还可以在运行时判断当前系统的版本,方式如下:

private void setUpActionBar() 
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
    

就是使用Build类的常量判断,Build类包含了当前系统中的众多信息,包括cpu类型,设备名称,制造商,序列号等等信息,更多信息参考Build的api doc:
https://developer.android.com/reference/android/os/Build.html
这里再啰嗦一句,当系统解析xml资源文件的时候,android会自动过滤掉不识别或者不支持的特性。比如说,你在xml文件中使用了ActionBar这个元素,但是这个元素是android 3.0以上的版本才能支持的,如果是一个低于3.0版本的设备来解析这个xml文件的话,会自动忽略这个元素,而不会产生任何错误。
除了以上提到的内容,android在界面效果上还有一些有关系统版本之间的内容。对于每个android版本,没有版本都会有自己的style和theme,也就是风格和主题。比如说2.3版本的风格和4.0的界面风格就是有很大的不同,4.0的风格更加时尚;5.0之后的风格和主题就发生更大的变化了,因为引入了“原质化设计(material design)”,使得界面更加自然淳朴。使用这些内置的风格和主题可以使得你的app再不同版本的系统中以一种和系统版本相适应的风格方式显示。目前google自定了很多风格和主题,可以在以下的链接中看到完整的内容:
风格和主题的介绍:
https://developer.android.com/guide/topics/ui/themes.html
系统内置风格:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/styles.xml
系统内置主题:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/themes.xml
我们比较常见的有:
对话框主题:

<activity android:theme="@android:style/Theme.Dialog">

透明背景:

<activity android:theme="@android:style/Theme.Translucent">

当然,我们也可以仿造上面系统预定义的方式,自定义风格和主题,定义的内容一般写在res/values/styles.xml中,这里是一个例子:

<style name="CodeFont">
     <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">wrap_content</item>
     <item name="android:textColor">#00FF00</item>
     <item name="android:typeface">monospace</item>
</style>

当然我们也可以继承自系统预定义的风格主题,使用parent关键字,比如:

<style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>

我们把上面的CodeFont风格继承自系统的TextAppearance.Medium风格了。更多的信息可以参考:
https://developer.android.com/guide/topics/ui/themes.html#DefiningStyles
我们使用主题或者风格的方式比较简单,如果相对某个activity应用主题风格可以这样:

<activity android:theme="@style/CustomTheme">

如果想对整个应用也就是所有的activity应用的话,可以这样:

<application android:theme="@style/CustomTheme">

关于风格和主题更加详细的资料,可以看看这个,解释的还是比较到位的(英文的,嘿嘿):
http://docs.appcelerator.com/platform/latest/#!/guide/Android_Themes

以上是关于Android Training学习笔记之适配不同的设备的主要内容,如果未能解决你的问题,请参考以下文章

Android官方开发文档Training系列课程中文版:多样屏幕之支持不同的屏幕尺寸

android开发笔记之打造终极适配器

Android官方开发文档Training系列课程中文版:通知用户之创建不同导航方式的Activity

Android适配全攻略(学习笔记总结)

学习设计模式之适配器模式

Android官方开发文档Training系列课程中文版:多样屏幕之实现自适应UI