Android适配
一、为什么使用适配:
安卓的设置在世界范围内具有很多的型号和尺寸,凭借广泛的设备类型,您有机会达到一个巨大的观众与您的应用程序,为了能够尽可能的成功在Android上,你的应用程序需要适应不同的器件配置。一些重要的变化,你应该考虑的因素包括不同的语言,屏幕尺寸,并且Android平台的版本。
(一)、支持不同的语言(internationalization (国际化)简称 i18n,因为在i和n之间还有18个字符,localization(本地化 ),简称L10n)
从您的应用程序代码中提取UI字符串并将其保存在外部文件是比较好的做法,安卓让这个简单,在每个Android的项目资源目录
1、支持不同的语言具体操作如下所示:
添加支持多种语言,在项目中res/目录下添加额外的values文件夹以国家代码作为名称的后缀。例如:values -es/这个文件夹中包含简单的语言代码”es”。android系统根据设备在运行时的语言环境设置加载相应的资源。
一旦你决定了你会支持的语言,创建资源子目录和字符串资源文件。例如:
MyProject/
res/
values/
strings.xml
values-es/
strings.xml
values-fr/
strings.xml
添加字符串值,每个区域设置成相应的文件。
在运行时, Android系统使用适当的设置基于当前对用户的设备设置本地化的字符串资源。
例如,下面是一些不同的字符串资源文件对于不同的语言。
英语 (default locale), /values/strings.xml:
西班牙语, /values-es/strings.xml:
法语, /values-fr/strings.xml:
2、string字符串资源的使用
您可以参考您的字符串资源,在你的源代码,并使用由
在源代码中,你可以参考与语法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 =newTextView(this);
textView.setText(R.string.hello_world);
在其他的XML文件,你可以参考一个字符串资源的语法@string/ < string_name >每当XML属性接受一个字符串值。
例如:
(二)、支持不同的屏幕
Android的分类使用两种通用性设备屏幕:大小和密度。应该考虑到,应用程序将与屏幕,范围规模和密度的设备上安装。因此,您应该包括优化您的应用程序的外观不同的屏幕尺寸和密度一些替代资源。
有四种广义的尺寸:小,正常,大, XLARGE
四广义密度:低( LDPI ) ,中( MDPI ) ,高(华电国际) ,特高( xhdpi )
声明不同的布局和位图,你想使用不同的屏幕上,你必须把这些替代资源在不同的目录,类似于你如何做不同的语言字符串。
另外要注意,屏幕方向(横向或纵向)被认为是屏幕尺寸的变化,所以许多应用程序应该修改布局优化中的每个方位的用户体验。
1、创建不同的布局文件
为了优化不同屏幕尺寸的用户体验,你应该为你想要支持每个屏幕尺寸独特的布局XML文件。每个布局应该保存到相应的资源目录,命名了 - < screen_size >后缀。例如,对于大屏幕独特的布局应该在res/layout-large/。
例如,该项目包含一个默认的布局和大屏幕的替代布局:
MyProject/
res/
layout/
main.xml
layout-large/
main.xml
文件名必须是完全一样的,但它们的内容是为了提供用于相应的屏幕尺寸优化的用户界面不同。
简单地引用布局文件在你的应用程序像往常一样:
@Override
protectedvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
系统加载的基础上,你的应用程序是运行在设备的屏幕大小合适的布局目录布局文件。
例如,这里有与横向的替代布局的项目:
MyProject/
res/
layout/
main.xml
layout-land/
main.xml
默认情况下,layout/main.xml 中文件用于纵向。
如果您想为景观特殊的布局,包括同时在大屏幕上,则需要同时需要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
2、 创建不同的位图
你应该总是提供适当比例给每个广义密度桶的位图资源:低,中,高和超高密度。这将帮助你实现良好的图形质量和性能上的所有屏幕密度。
产生这些图像,你应该开始与你的矢量格式的原始资源,并产生使用以下规模大小各密度的图像:
- xhdpi: 2.0
- hdpi: 1.5
- mdpi: 1.0 (baseline)
- ldpi: 0.75
这意味着,如果你生成一个200x200的图像xhdpi设备,就应生成LDPI设备相同的资源在150×150的华电国际, 100×100的MDPI和75x75 。
然后,将在适当的绘制资源目录中的文件:
MyProject/
res/
drawable-xhdpi/
awesomeimage.png
drawable-hdpi/
awesomeimage.png
drawable-mdpi/
awesomeimage.png
drawable-ldpi/
awesomeimage.png
您引用@drawable/ awesomeimage任何时候,系统会选择基于屏幕的密度适当的位图。
3、如何通过支持不同的屏幕尺寸:
确保你的布局可以充分地调整以适应屏幕
根据屏幕配置提供了相应的UI布局
确保正确的布局被施加到正确的屏幕
提供了扩展正确的位图
3.1、Use “wrap_content” and “match_parent”
为了确保你的布局非常灵活,适应不同的屏幕尺寸,应使用“ wrap_content ”和“ match_parent ”为一些视图组件的宽度和高度。如果使用“ wrap_content ”时,视图的宽度或高度设定为最小尺寸需要该视图内的适合的内容,而“ match_parent ” ( API级别8日前也被称为“ FILL_PARENT ”),使得组件扩展,以便与其父视图的大小。
通过使用“ wrap_content ”和“ match_parent ”大小的值,而不是硬编码的大小,你的意见或者使用只要求该视图的空间或扩展以填充可用空间。例如:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<LinearLayoutandroid:layout_width=”match_parent”
android:id=”@+id/linearLayout1”
android:gravity=”center”
android:layout_height=”50dp”>
<ImageViewandroid:id=”@+id/imageView1”
android:layout_height=”wrap_content”
android:layout_width=”wrap_content”
android:src=”@drawable/logo”
android:paddingRight=”30dp”
android:layout_gravity=”left”
android:layout_weight=”0”/>
<Viewandroid:layout_height=”wrap_content”
android:id=”@+id/view1”
android:layout_width=”wrap_content”
android:layout_weight=”1”/>
<Buttonandroid:id=”@+id/categorybutton”
android:background=”@drawable/button_bg”
android:layout_height=”match_parent”
android:layout_weight=”0”
android:layout_width=”120dp”
style=”@style/CategoryButtonStyle”/>
</LinearLayout>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”match_parent”/>
</LinearLayout>
请注意该示例使用“ wrap_content ”和“ match_parent ”的分量大小,而不是具体的尺寸。这使得布局能够正确适应不同的屏幕尺寸和方向。
3.2、使用相对布局
您可以建立使用的LinearLayout和嵌套实例“ wrap_content ”和“ match_parent ”大小的组合相当复杂的布局。然而, LinearLayout中不允许您精确地控制子控件的意见空间关系;意见中的LinearLayout只需排队并排侧,如果你需要子控件的意见,以定向在变化比直线等,更好的解决方案往往是使用RelativeLayout ,它允许你指定组件之间的空间关系方面的布局。例如,您可以对齐左侧一个子视图,在屏幕右侧的另一种观点。
例如:
<RelativeLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<Button
android:id=”@+id/ok”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_below=”@id/entry”
android:layout_alignParentRight=”true”
android:layout_marginLeft=”10dp”
android:text=”OK”/>
<Button
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_toLeftOf=”@id/ok”
android:layout_alignTop=”@id/ok”
android:text=”Cancel”/>
</RelativeLayout>
3.3 使用尺寸限定
你可以从一个灵活的布局和相对布局像一个在前面的章节中获得。而那些布局由内及周围部件伸展空间适应不同的屏幕,它们可能不提供用于每个画面大小最佳的用户体验。因此,您的应用程序不仅要实现灵活的布局,也应该提供几种可供选择的布局,针对不同的屏幕配置。您可以通过使用配置预选赛,这使得运行时自动选择基于当前设备的配置相应的资源(如不同的布局设计,不同的屏幕尺寸)这样做。
例如,许多应用程序实现了“两个窗格”模式为大屏幕(应用程序,可能有物品的上一个窗格的列表,并在另一窗格中的内容) 。平板电脑和电视是足够大的两个窗格同时适应在屏幕上,但手机屏幕必须单独显示它们。因此,要实现这些布局,你可以有以下文件:
res/layout/main.xml,单窗格(默认)布局:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”match_parent”/>
</LinearLayout>
res/layout-large/main.xml 双面版布局
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:orientation=”horizontal”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”400dp”
android:layout_marginRight=”10dp”/>
<fragmentandroid:id=”@+id/article”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.ArticleFragment”
android:layout_width=”fill_parent”/>
</LinearLayout>
请注意,large限定符在第二布局的目录名。这种布局将在设备中选择与分类为大的(例如,7“片剂及以上)的屏幕。其它布局(无限定符)将被选择为更小的设备。
3.4 使用最短—宽度限定
困难之一开发者在前期3.2的Android设备是“大”屏幕尺寸,其中包括了戴尔Streak ,原来的Galaxy Tab ,和一般的7 “平板电脑,但是,许多应用程序可能需要显示不同的布局这个类别中的不同设备(如5 “和7”的设备) ,即使它们都被认为是“大”的画面,这就是为什么机器人推出的“最小宽度”限定符(主要)中的Android 3.2 。
最小宽度的限定可以让您针对那些在DP给予一定的最小宽度的屏幕。例如,典型的7“平板电脑拥有600 DP的最小宽度,因此,如果你希望你的用户界面,以对这些屏幕两个窗格(但在小屏幕上一个列表) ,您可以使用两个相同的布局,从上一节单和双面板的布局,而是大尺寸限定,使用sw600dp来表示两个窗格布局是屏幕上的最小宽度为600 DP:
res/layout/main.xml,单窗格(默认)布局:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”match_parent”/>
</LinearLayout>
res/layout-sw600dp/main.xml,双面板布局:
-
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:orientation=”horizontal”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”400dp”
android:layout_marginRight=”10dp”/>
<fragmentandroid:id=”@+id/article”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.ArticleFragment”
android:layout_width=”fill_parent”/>
</LinearLayout>
这意味着设备的最小宽度大于或等于600dp将选择布局 layout-sw600dp/main.xml中(两窗格)布局,而小屏幕会选择layout/main.xml中(单面板)的布局。
不过,这不会预先3.2设备工作良好,因为他们不承认sw600dp作为大小预选赛,所以你仍然需要使用大量预选赛以及。所以,你应该有一个文件名为res/layout-large/main.xml中是相同的res/layout-sw600dp/main.xml中。在下一节中,你会看到一种技术,它可以让你避免重复布局文件这种方式。
3.5 使用布局别名
最小宽度预选赛仅在Android 3.2及以上。因此,你应该也还在用抽象箱尺寸(小,正常,大, XLARGE )要与早期版本兼容。例如,如果你想设计自己的界面,因此它显示在手机上的单一窗格的用户界面,但7 “平板电脑,电视等大型设备多窗格用户界面,你必须提供以下文件:
- res/layout/main.xml: 单面版布局
- res/layout-large: 多面版布局
- res/layout-sw600dp: 多面版布局
最后两个文件是相同的,因为他们中的一个将搭载Android 3.2的设备相匹配,另一种是用于平板电脑和与早期版本的Android电视的好处。
为了避免这种重复同一个文件的平板和电视 ,您可以使用别名文件。例如,您可以定义以下布局:
- res/layout/main.xml,单面版布局
- res/layout/main_twopanes.xml, 多面版布局
添加两个文件:
-
res/values-large/layout.xml:
<itemname="main"type="layout">@layout/main_twopanes</item> -
res/values-sw600dp/layout.xml:
<itemname="main"type="layout">@layout/main_twopanes</item>
这些后面的两个文件具有相同的内容,但它们实际上并不定义布局。他们只是设立主要是一个别名main_twopanes 。因为这些文件具有large和sw600dp选择器,它们被施加到片剂和电视不管Android版(预3.2平板和电视相匹配的大,和后3.2将匹配sw600dp ) 。
3.6 使用方向限定
有些布局在横向和纵向方向运行良好,但大多可以从调整中受益。在新闻阅读器示例应用程序,这里是如何布局的行为在每个屏幕的大小和方向:
- small screen, portrait: single pane, with logo
- small screen, landscape: single pane, with logo
- 7” tablet, portrait: single pane, with action bar
- 7” tablet, landscape: dual pane, wide, with action bar
- 10” tablet, portrait: dual pane, narrow, with action bar
- 10” tablet, landscape: dual pane, wide, with action bar
- TV, landscape: dual pane, wide, with action bar
所以每个布局中在res/layout/目录中的XML文件中定义。向然后分配给每个布局的各种屏幕的配置中,应用程序使用布局别名它们相互配合结构:
res/layout/onepane.xml:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”match_parent”/>
</LinearLayout>
res/layout/onepane_with_bar.xml:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<LinearLayoutandroid:layout_width=”match_parent”
android:id=”@+id/linearLayout1”
android:gravity=”center”
android:layout_height=”50dp”>
<ImageViewandroid:id=”@+id/imageView1”
android:layout_height=”wrap_content”
android:layout_width=”wrap_content”
android:src=”@drawable/logo”
android:paddingRight=”30dp”
android:layout_gravity=”left”
android:layout_weight=”0”/>
<Viewandroid:layout_height=”wrap_content”
android:id=”@+id/view1”
android:layout_width=”wrap_content”
android:layout_weight=”1”/>
<Buttonandroid:id=”@+id/categorybutton”
android:background=”@drawable/button_bg”
android:layout_height=”match_parent”
android:layout_weight=”0”
android:layout_width=”120dp”
style=”@style/CategoryButtonStyle”/>
</LinearLayout>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”match_parent”/>
</LinearLayout>
res/layout/twopanes.xml:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:orientation=”horizontal”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”400dp”
android:layout_marginRight=”10dp”/>
<fragmentandroid:id=”@+id/article”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.ArticleFragment”
android:layout_width=”fill_parent”/>
</LinearLayout>
res/layout/twopanes_narrow.xml:
<LinearLayoutxmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:orientation=”horizontal”>
<fragmentandroid:id=”@+id/headlines”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.HeadlinesFragment”
android:layout_width=”200dp”
android:layout_marginRight=”10dp”/>
<fragmentandroid:id=”@+id/article”
android:layout_height=”fill_parent”
android:name=”com.example.android.newsreader.ArticleFragment”
android:layout_width=”fill_parent”/>
</LinearLayout>
现在,所有可能的布局定义,它的使用配置预选赛映射正确的布局,以每种配置的问题而已。现在,您可以使用布局别名技术,它做的:
res/values/layouts.xml:
res/values-sw600dp-land/layouts.xml:
res/values-sw600dp-port/layouts.xml:
res/values-large-land/layouts.xml:
res/values-large-port/layouts.xml:
3.7 Use Nine-patch Bitmaps
支持不同的屏幕尺寸通常意味着你的形象资源,还必须能够适应不同尺寸的。例如,一个按钮背景必须适合取按钮形状被应用到。
如果您对组件,可以改变大小使用简单的图像,你会很快发现,结果是令人印象深刻的比稍差,因为运行时会伸长或收缩均匀的图像。该溶液是用9 -补丁的位图,这是特殊格式PNG文件指示哪些区域和不能被拉伸。
因此,在设计的位图将与可变大小的组件一起使用时,一定要使用九补丁。要转换位图到九补丁,你可以用普通的图像(图 ,在4倍变焦的清晰显示)开始。
图. button.png
然后通过SDK (它位于tools/目录) ,在其中您可以标记应通过绘制沿左侧和顶部边框的像素被拉伸区域的draw9patch工具运行它。你也可以标记应该通过绘制像素沿右侧和底部边界,导致在图中保持的内容的区域。
图. button.9.png
请注意,黑色像素沿边界。在顶部和左边框的那些表示在图像可拉伸的地方,并在右边和底部边界的那些指明的内容应该放置。
此外,请注意 .9.png扩展。您必须使用这个扩展,因为这是怎样的框架检测,这是一个九补丁的形象,而不是一个普通的PNG图像。
当应用此背景成分(通过设置android:background=”@drawable/button” ) ,该框架正确地伸展的图像,以容纳按键的尺寸,如在图6中所示的各种尺寸。
图. 使用 button.9.png九片不同大小的按钮。
(三)、支持不同的平台版本
而Android的最新版本经常为你的应用程序提供了极大的API ,你应该继续支持旧版本的Android ,直到更多的设备得到更新。
仪表板为平台版本会定期更新,以显示运行的每个版本的Android ,基于该访问谷歌Play商店的设备数量有源器件的分布。一般情况下,这是一个很好的做法,支持约90%的有源器件,而针对您的应用程序到最新版本。
1.指定最小和目标的API级别
AndroidManifest.xml文件描述了你的应用程序识别的Android系统版本,它支持的详细信息。具体来说, minSdkVersion和targetSdkVersion属性的 <uses-sdk 元素识别API的最低水平,你的应用程序是兼容的,最高级别的API对您所设计和测试您的应用程序。
例如:
<manifestxmlns:android=”http://schemas.android.com/apk/res/android” … >
<uses-sdkandroid:minSdkVersion=”4”android:targetSdkVersion=”15”/>
…
</manifest>
由于Android的新版本发布时,一些风格和行为可能会改变。为了让您的应用程序把这些变化的优势,并确保您的应用程序适合每个用户的设备的风格,你应该设置targetSdkVersion值,以符合最新的Android版本。
2.运行时检查系统版本
Android提供了对每个平台的版本生成的常量类的唯一代码。使用你的应用程序中,这些代码来构建,以确保执行依赖于较高的API级别,只有当这些API都可以在系统上的代码的条件。
privatevoid 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);
}
}
3.使用的平台风格和主题
Android提供了用户体验的主题,让应用程序的底层操作系统的外观和感觉。这些主题可以应用到你的应用程序清单文件中。通过使用这些内置的风格和主题,你的应用程序自然会跟着最新的Android外观和感觉与每个新版本。
为了使您的活动看起来像一个对话框:
<activityandroid:theme=”@android:style/Theme.Dialog”>
为了使你的活动有一个透明的背景:
<activityandroid:theme=”@android:style/Theme.Translucent”>
适用于/res/values/styles.xml定义您自己的自定义主题:
<activityandroid:theme=”@style/CustomTheme”>
为了将主题应用到整个应用程序(所有活动) ,添加了 android:theme 属性的
<applicationandroid:theme=”@style/CustomTheme”>
sp、dp、dip、pt、px等单位的区别?
- dpi dpi指像素密度。dots per inch ,即每英寸内像素点的个数。它不是表示长度的单位。
-
- 在android中认为:低(120dpi),中(160dpi),高(240dpi),超高(320dpi)。随着技术的增长,实际dpi已经超出这个定义范围。
- dip device independent pixels ,即与设备无关的像素。目前这个单位已经被dp所取代,而不建议使用dip。
- dp 与dip的概念一样。不过dp已经取代了dip。在Android中用来表示非文字大小的尺寸。例如:外边距、内填充等。
-
- px = dp * (dpi / 160)
- 3.7寸屏幕,分辨率320*480手机上,正好1px = 1dp。
- sp scale independent pixel ,即与缩放比例无关的像素。在android中常用来表示文字大小。
- px 表示像素。因为同样是200px,但是在不同手机下显示的大小是不同的。
- pt point磅。1磅=1/74英寸
- xlarge 屏幕至少:960dp x 720dp
- large 屏幕至少 :640dp x 480dp
- normal 屏幕至少 :470dp x 320dp
- small 屏幕至少 :426dp x 320dp