随着android智能手机的发展和普及,各种各样的大小和尺寸的android智能机不断的退出,通过各种各样的设备机型,我们能够让自己的APP接触到广大的用户。为了能在各种android平台上使用,我们的APP需要兼容不同的设备类型,比如语言,屏幕尺寸,android系统的版本等重要的变量因素。希望能够通过这次总结,复习符合使用基础的平台功能,利用替代资源和其他功能,使APP仅用一个程序包,就能想用android兼容设备的用户提供更好的用户体验
把UI中的字符串存储到外部文件,通过代码提取这种方式可以实现。当我们通过AS创建一个项目工程的时候,就会在工程的根目录中创建一个res的目录,目录中包含所有的资源类型的子目录。其中就包好工程的默认文件res/values/strings.xml,用于保存字符串值。
为了支持多国语言,在res中创建一个额外的values目录,以连字符和ISO国家代码结尾来命名,如果决定支持某种语言,则需要创建资源子目录和字符串资源文件
添加不同区域语言的字符串值到相应的文件
android系统运行时,会根据当前用户的区域设置,使用相应的字符串资源。
如下几个不同语言对应的不同字符串资源
英语(默认区域语言) values/strings.xml
<resources>
<string name="app_name">Android_Demo_01string>
resources>
西班牙语: values-es/strings.xml
<resources>
<string name="title">Mi Aplicaciónstring>
<string name="hello_world">Hola Mundo!string>
resources>
法语: values-fr/strings.xml
<resources>
<string name="title">Mon Applicationstring>
<string name="hello_world">Bonjour le monde !string>
resources>
我们可以通过源代码和其他XML文件总通过元素的name属性来引入自己的字符串资源
在源代码中可以通过R.string.语法来引入一个字符串资源,很多方法都可以通过这种方式来接受字符串
String ss = getResources().getString(R.string.app_name);
在其他的XML文件中,每当XML属性需要接受一个字符串值时,我们可以通过@string/的方式来引入
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
使得某一元素在android不同尺寸,不同分辨率的手机上具备相同的显示效果
目前来说android常见的尺寸有5寸,5.5寸,6寸
一般描述成屏幕的”宽x高”=AxB
含义: 屏幕在横向上有A个像素点,在纵向上有B个像素点
例如:1080x1920 即宽度上有1080个像素点,高度上有1920个像素点
单位:px 1px = 1像素
android常见的分辨率是320x480 480x800 720x1280 1080x1920
假设设备每英寸有160个像素,该设备的屏幕像素度是160dpi
密度类型 | 代表的分辨率(px) | 屏幕像素密度(dpi) |
---|---|---|
低密度(ldpi) | 240x320 | 120 |
中密度(mdpi) | 320x480 | 160 |
高密度(hdpi) | 480x800 | 240 |
超高密度(xhdpi) | 720x1280 | 320 |
超超高密度(xxhdpi) | 1080x1920 | 480 |
- android开发室用dp而不是px单位设置图片大小,是android特有的单位
- 场景:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度
密度类型 | 代表的分辨率(px) | 屏幕密度(dpi) | 换算(px/dp) | 比例 |
---|---|---|---|---|
低密度(ldpi) | 240x320 | 120 | 1dp=0.75px | 3 |
中密度(mdpi) | 320x480 | 160 | 1dp=1px | 4 |
高密度(hdpi) | 480x800 | 240 | 1dp=1.5px | 6 |
超高密度(xhdpi) | 720x1280 | 320 | 1dp=2px | 8 |
超超高密度(xxhdpi) | 1080x1920 | 480 | 1dp=3px | 12 |
在android中,规定以160dpi(即分辨率为320x480为基准),1dp = 1px
- Android开发时用此单位设置文字大小,可根据字体大小首选项进行缩放
- 荐使用12sp、14sp、18sp、22sp作为字体设置的大小,不推荐使用奇数和小数,容易造成精度的丢失问题;小于12sp的字体会太小导致用户看不清
以上是基本概念,需要牢记
使得布局,布局组件自适应屏幕尺寸
根据屏幕的配置来加载相应的UI布局和用户界面流程
android中的布局样式分为4种
1. 线性布局
2. 相对布局
3. 帧布局
4. 绝对布局
针对不同的布局我们需要在不同的场景下使用
代码展示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:id="@+id/headlines"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.HeadlinesFragment"
android:layout_width="match_parent" />
LinearLayout>
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
id="@+id/headlines"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.HeadlinesFragment"
android:layout_width="400dp"
android:layout_marginRight="10dp"/>
id="@+id/article"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.ArticleFragment"
android:layout_width="fill_parent" />
当屏幕最小宽度大于或者等于600dp的设备,系统会自动加载layout-sw600dp、main.xml布局。否则系统就会选择默认布局
注意,这里的最小宽度限定符仅用于android3.2以后的版本
像上面的例子中,我们已经拥有了两个不同的布局文件,那么为了能够能够适配不同尺寸,我们可以通过使用布局别名的方式
然后加入以下的两个文件,
1.res/values-large/layout.xml (默认)
<resources>
<item name="main" type="layout">@layout/main_twopanesitem>
resources>
2.res/values-sw600dp/layout.xml
<resources>
<item name="main" type="layout">@layout/main_twopanesitem>
resources>
a. 版本低于3.2的会自动匹配large的文件
b. 版本高于3.2的会自动匹配sw600dp的文件
以上的两个layout.xml文件可以引入相同的文件,避免了重复定义布局文件的情况
使用场景: 根据屏幕方向进行布局调整
小屏幕, 竖屏: 单面板
小屏幕, 横屏: 单面板
7 英寸平板电脑,纵向:单面板,带操作栏
7 英寸平板电脑,横向:双面板,宽,带操作栏
10 英寸平板电脑,纵向:双面板,窄,带操作栏
10 英寸平板电脑,横向:双面板,宽,带操作栏
电视,横向:双面板,宽,带操作栏
方法是
1.先定义类别: 单/双面板,是否带操作栏,宽/窄
定义在res/layout/目录下的某个XML文件中
2.在进行相应的匹配: 屏幕尺寸(小屏 7寸 10寸) 方向(横,纵)
使用布局别名进行匹配
步骤:
1. 在res/layout/目录下的某个XML文件中定义所需要的布局类型
res/layout/onepane.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android: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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:id="@+id/linearLayout1"
android:gravity="center"
android:layout_height="50dp">
<ImageView android: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" />
<View android:layout_height="wrap_content"
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_weight="1" />
<Button android: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>
<fragment android: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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<fragment android:id="@+id/headlines"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.HeadlinesFragment"
android:layout_width="400dp"
android:layout_marginRight="10dp"/>
<fragment android: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(双面板,窄布局)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<fragment android:id="@+id/headlines"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.HeadlinesFragment"
android:layout_width="200dp"
android:layout_marginRight="10dp"/>
<fragment android:id="@+id/article"
android:layout_height="fill_parent"
android:name="com.example.android.newsreader.ArticleFragment"
android:layout_width="fill_parent" />
LinearLayout>
2.使用布局别名进行相应的匹配
res/values/layouts.xml
<resources>
<item name="main_layout" type="layout">@layout/onepane_with_baritem>
<bool name="has_two_panes">falsebool>
resources>
可为resources设置bool,通过获取其值来动态判断目前已处在哪个适配布局
res/values-sw600dp-land/layouts.xml
大屏、横向、双面板、宽-Andorid 3.2版本后
<resources>
<item name="main_layout" type="layout">@layout/twopanesitem>
<bool name="has_two_panes">truebool>
resources>
res/values-sw600dp-port/layouts.xml
(大屏、纵向、单面板带操作栏-Andorid 3.2版本后)
<resources>
<item name="main_layout" type="layout">@layout/onepaneitem>
<bool name="has_two_panes">falsebool>
resources>
res/values-large-land/layouts.xml
(大屏、横向、双面板、宽-Andorid 3.2版本前)
<resources>
<item name="main_layout" type="layout">@layout/twopanesitem>
<bool name="has_two_panes">truebool>
resources>
res/values-large-port/layouts.xml
(大屏、纵向、单面板带操作栏-Andorid 3.2版本前)
<resources>
<item name="main_layout" type="layout">@layout/onepaneitem>
<bool name="has_two_panes">falsebool>
resources>
这里并没有写完,可自行补充
使得布局组件自适应屏幕尺寸
使用wrap_content,match_parent和weight来控制试图组件的宽度和高度
关于weigth权重的问题,这边有个小哥哥,写的很好,可供参考androidweight权重
使得图片资源在不同屏幕密度上显示相同的像素效果
- 使用自动拉伸位图:Nine-patch的图片类型
假设需要匹配不同屏幕大小,你的图片资源也必须自动适应各种屏幕尺寸
例如:一个按钮的背景图片必须随着按钮的大小改变而改变
解决方案: 使用自动拉伸位图,后缀名.9.png,它是一种被特殊处理过的png图片,设计师可以指定图片的拉伸区域和非拉伸区域,使用时,系统会根据空间大小自动的拉伸你想要拉伸的部分
我们应该为四种普通分辨率:高,中,低,超高精度,都提供相应设配的bitmap资源
要生成这些图像,应该从原始的矢量图像资源着手,然后根据下列尺寸比例,生成各种密度的图像
这也就意味着,如果针对xhdpi的设备生成了一张200x200的图像,那么应该为hdpi生成150x150,为mdpi生成100x100, 和为ldpi生成75x75的图片资源
然后在将这些文件放在相应的drawable资源目录中
任何时候,当引用@drawable/ic_launch是系统就会自动使用恰当的bitmap
新的Android版本会为我们的app提供更棒的APIs,但我们的app仍应支持旧版本的Android,直到更多的设备升级到新版本为止
当我们通过AS创建一个应用时,有一些地方的数据信息对我们开发APP应用是有很大的帮助的
所以,在一般情况下,在更新APP到最新版本的android时,最好保证新版本的APP可以支持90%
android的清单配置文件中描述了我们的APP的细节,以及APP支持哪些android版本。具体说元素中的minSdkVersion和targetSdkVersion属性,表明了在设计和测试APP是最低兼容API的级别和最高使用的API级别
当然现在这个属性设置在了gradle中
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.paul.android_demo_01"
minSdkVersion 18
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
随着新版本Android的发布,一些风格和行为可能会改变,为了能使app能利用这些变化,而且能适配不同风格的用户的设备,我们应该将targetSdkVersion的值尽量的设置与最新可用的Android版本匹配
android在build常量类中提供了对每一个版本的唯一代号,在我们的APP中使用这些代号可以建立条件,保证依赖于高级别的API代码,只会在这些API在当前系统中可用
private void setUpActionBar(){
//确保我们当前运行的版本是大于等于Honeycomb版本(sdk11)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
android.app.ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
}
Android提供了用户体验主题,为app提供基础操作系统的外观和体验。这些主题可以在manifest文件中被应用于app中。通过使用内置的风格和主题,我们的app自然地随着Android新版本的发布,自动适配最新的外观和体验.
例如
使activity看起来像一个对话框:
<activity android:theme="@android:style/Theme.Dialog">
使Activity看起来透明的背景
<activity android:theme="@android:style/Theme.Translucent">
应用在/res/values/styles.xml中定义的自定义主题:
<activity android:theme="@style/CustomTheme">
使整个app应用一个主题(全部activities)在元素中添加android:theme属性:
<application android:theme="@style/CustomTheme">
未完待续···
android官方培训课-胡凯大神翻译整理
stormzhang:android屏幕设配
鸿祥:android屏幕适配方案
郭霖大神:android官方提供的支持不同屏幕大小的方法