1.关于 Android 屏幕适配
1.1 什么是 Android 屏幕适配
使得一些元素在 Android 不同尺寸,不同分辨率的手机上具备相同且合适的显示效果。
1.2 为什么要进行 Android 屏幕适配
- Android 碎片化:由于Android系统的开放性,任何用户、开发者、硬件厂商、运营商都可以对Android系统和硬件进行定制,修改成他们想要的样子。
- Android 系统碎片化:基于Google原生系统,小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等
- Android 屏幕尺寸碎片化:5寸、5.5寸、6寸等
- Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920等
- 导致的结果:容易出现同一元素在不同手机上显示效果不同的问题
- 综上:为了保证用户获得一致的用户体验效果,使得某一元素在Android不同尺寸、不同分辨率的、不同系统的手机上具备相同的显示效果,能够保持界面上的效果一致,我们需要对各种手机屏幕进行适配
2.相关重要概念
2.1 屏幕尺寸
指屏幕的对角线的长度
单位是英寸,1英寸=2.54厘米,常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等
2.2 屏幕分辨率
指在横纵向上的像素点数
单位是px,1px=1个像素点。一般以纵向像素* 横向像素,如1960*1080
2.3 屏幕像素密度
指每英寸上的像素点数
单位是dpi,即“dot per inch”的缩写。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。
2.3 dp,dip,dpi,sp,px
- dp:和dip 是一个意思,都是Density Independent Pixels的缩写,即密度无关像素
- dpi:屏幕像素密度,假如一英寸里面有160个像素,这个屏幕的像素密度就是160dpi
- dp与px的转换:
ui设计师给我们的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么我们需要进行转换,在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1px=2dp,具体如下表:
密度类型 | 代表的分辨率(px) | 屏幕密度(dpi) | 换算(px/dp) | 比例 |
---|---|---|---|---|
低密度(ldpi) | 240x320 | 120 | 1px=0.75dp | 3 |
中密度(mdpi) | 320x480 | 160 | 1px=1dp | 4 |
高密度(hdpi) | 480x800 | 240 | 1px=1.5dp | 6 |
超高密度(xhdpi) | 720x1280 | 320 | 1px=2dp | 8 |
超超高密度(xxhdpi) | 1080x1920 | 480 | 1px=3dp | 12 |
转换过程 | 转换公式 | 示例 |
---|---|---|
dp单位转换成px单位 | px = dp* (devicePixelRatio)= dp*(density/160) | 假如density(像素密度)为320,把360dp转换成px,那么最终像素=360dp*(320/160)=720px |
px单位转换成dp单位 | dp = px * (devicePixelRatio)=px * (density/160) | 假如density(像素密度)为320,把640dp转换成px,那么最终像素=640dp*(320/160)=1280px |
- 使用px作为单位的,在不同的设备中会显示不同的效果,使用dp作为单位的,会根据不同的设备进行转化,适配不同机型。所以建议在长度宽度的数值使用dp作为单位
- 使用sp作为字体大小单位,会随着系统的字体大小改变,而dp作为单位则不会。所以建议在字体大小的数值要使用sp作为单位
2.4 mdpi,hdpi,xdpi,xxdpi
用来修饰Android中的drawable文件夹及values文件夹,以区分不同像素密度下的图片和dimen值。
在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面
- 如何区分?Google官方指定按照下列标准进行区分:
名称 | 像素密度范围 |
---|---|
mdpi | 120dpi~160dpi |
hdpi | 160dpi~240dpi |
xhdpi | 240dpi~320dpi |
xxhdpi | 320dpi~480dpi |
xxxhdpi | 480dpi~640dpi |
名称 | 图标尺寸 |
---|---|
mdpi | 48x48px |
hdpi | 72x72px |
xhdpi | 96x96px |
xxhdpi | 144x144px |
xxxhdpi | 192x192px |
3.解决方案:(如何适配)
3.1 支持各种屏幕尺寸
3.1.1 使用 wrap_content,match_parent,weight
3.1.2 使用相对布局,禁用绝对布局(绝对布局适配性差)
- 效果:使得不同元素自适应屏幕尺寸
3.1.3 使用限定符
通过布局拉伸组件内外的空间以适应各种屏幕,但它们不一定能为每种屏幕都提供最佳的用户体验,应该应针对各种屏幕配置提供一些备用布局,故使用限定符,在运行时根据当前的设备配置自动选择合适的资源了,例如根据各种屏幕尺寸选择不同的布局。
a 使用尺寸限定符
- 使用场景:当一款应用显示的内容较多,希望进行以下设置
- 在平板电脑和电视的屏幕(>7英寸)上:实施“双面板”模式以同时显示更多内容
- 在手机较小的屏幕上:使用单面板分别显示内容
因此,我们可以使用尺寸限定符(layout-large)通过创建一个文件来完成上述设定:
res/layout-large/main.xml
文件配置如下:
- 适配手机的单面板(默认)布局:res/layout/main.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>
- 适配尺寸>7寸平板的双面板布局::res/layout-large/main.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>
- 请注意:这种方式只适合Android 3.2版本之前
- 两个布局名称均为main.xml,只有布局的目录名不同:第一个布局的目录名为:layout,第二个布局的目录名为:layout-large,包含了尺寸限定符(large)
- 被定义为大屏的设备(7寸以上的平板)会自动加载包含了large限定符目录的布局,而小屏设备会加载另一个默认的布局
b. 最小宽度(Smallest-width)限定符
- 背景:上述提到的限定符“large”具体是指多大呢?似乎没有一个定量的指标,这便意味着可能没办法准确地根据当前设备的配置(屏幕尺寸)自动加载合适的布局资源
- 例子:比如说large同时包含着5寸和7寸,这意味着使用“large”限定符的话我没办法实现为5寸和7寸的平板电脑分别加载不同的布局
最小宽度限定符可让您通过指定某个最小宽度(以 dp 为单位)来定位屏幕。例如,标准 7 英寸平板电脑的最小宽度为 600 dp,因此如果您要在此类屏幕上的用户界面中使用双面板(但在较小的屏幕上只显示列表),您可以使用上文中所述的单面板和双面板这两种布局,但您应使用 sw600dp 指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large 尺寸限定符。
- res/layout/main.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-sw600dp/main.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>
也就是说,对于最小宽度大于等于 600 dp 的设备,系统会选择 layout-sw600dp/main.xml(双面板)布局,否则系统就会选择 layout/main.xml(单面板)布局。
Android 版本低于 3.2 的设备不支持此技术,原因是这些设备无法将 sw600dp 识别为尺寸限定符,因此我们仍需使用 large 限定符
3.1.4 使用布局别名
- 场景:
当你需要同时为Android 3.2版本前和Android 3.2版本后的手机进行屏幕尺寸适配的时候,由于尺寸限定符仅用于Android 3.2版本前,最小宽度限定符仅用于Android 3.2版本后,所以这会带来一个问题,为了很好地进行屏幕尺寸的适配,你需要同时维护layout-sw600dp和layout-large的两套main.xml平板布局,如下:
适配手机的单面板(默认)布局:res/layout/main.xml
适配尺寸>7寸平板的双面板布局(Android 3.2前):res/layout-large/main.xml
适配尺寸>7寸平板的双面板布局(Android 3.2后)res/layout-sw600dp/main.xml
最后的两个文件的xml内容是完全相同的,这会带来:文件名的重复从而带来一些列后期维护的问题
于是为了要解决这种重复问题,我们引入了“布局别名”
还是上面的例子,你可以定义以下布局:
- 适配手机的单面板(默认)布局:res/layout/main.xml
- 适配尺寸>7寸平板的双面板布局:res/layout/main_twopanes.xml
然后加入以下两个文件,以便进行Android 3.2前和Android 3.2后的版本双面板布局适配:
- res/values-large/layout.xml(Android 3.2之前的双面板布局)
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
- res/values-sw600dp/layout.xml(Android 3.2及之后的双面板布局)
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
- 由于这些文件包含 large 和 sw600dp 选择器,因此,系统会将此文件匹配到不同版本的>7寸平板上:
a. 版本低于 3.2 的平板会匹配 large的文件
b. 版本高于 3.2 的平板会匹配 sw600dp的文件 - 最后两个文件有着相同的内容,但是它们并没有真正去定义布局,它们仅仅只是将main设置成了@layout/main_twopanes的别名
3.1.5 .使用自动拉伸位图
图片资源能够适应各种尺寸
- 解决方法:自动拉伸位图,这是一种格式特殊的 PNG 文件,其中会指明可以拉伸以及不可以拉伸的区域
参考链接
网友评论