相信做手机端的 App 的小伙伴,只要是产品稍微大一点,就会面临屏幕适配的问题,对于适配这个问题,网上众说纷纭,以前虽然有零零散散的看过,但是没有实践过,也是在最近遇到这个需求的情况下才研究了一下,现在做个记录。
1 参考链接
http://blog.csdn.net/qq_34161388/article/details/73469319
首先需要明白一些概念,比如什么是 px,什么是 dp,什么是 dpi,讲这些概念的文章很多,推荐一个:
http://www.jianshu.com/p/ec5a1a30694b
2 例子对比
Google 官方推荐在写布局文件的时候使用 dp,在分辨率相差不大的情况下,dp 确实能自己进行一定适配,但是如果分辨率比较大的时候,还是会有问题,随便写个布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginLeft="100dp"
android:layout_marginTop="250dp"
android:src="@mipmap/ic_launcher" />
</RelativeLayout>
上面两个图,左边是Galaxy Core mini,分辨率为 800x480,右边是魅蓝 metal,分辨率 1920x1080,可以看到还是有明显差别的,这个时候我们就应该想到适配,那么适配的方式有很多,比如洋神的 AutoLayout(已经停止维护了,不建议在项目中使用),还有写多个 layout 布局呀,还有 dimens 适配呀等等,在对比了多种方法后,最后我采用了 dimens 适配这种方式。这样的适配方式虽然会加入很多不同分辨率的 dimens 文件,但是比起写多个 layout 布局,要修改 UI 的时候需要修改很多 layout 的情况,还是要方便一点,最主要的是写布局的时候方便一点。
3 使用方法
使用方法也就是建立多个不同分辨率的 values 文件夹,比如主流的分辨率:values-800x480、values-1280x720、values-1920x1080,而在 Android 中规定是以 480x320 为基准的,所以这个可以放到默认的 values 文件夹下:
然后在每个文件夹下放对应的 dimens.xml 文件。比如默认的 values 文件夹下面的 dimens 文件是这样的:
<?pxml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="px1">1px</dimen>
<dimen name="px2">2px</dimen>
<dimen name="px3">3px</dimen>
<dimen name="px4">4px</dimen>
......
<dimen name="px1397">1397px</dimen>
<dimen name="px1398">1398px</dimen>
<dimen name="px1399">1399px</dimen>
<dimen name="px1400">1400px</dimen>
</resources>
<?pxml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="px1">2.25px</dimen>
<dimen name="px2">4.5px</dimen>
<dimen name="px3">6.75px</dimen>
<dimen name="px4">9px</dimen>
......
<dimen name="px1397">3143.25px</dimen>
<dimen name="px1398">3145.5px</dimen>
<dimen name="px1399">3147.75px</dimen>
<dimen name="px1400">3150px</dimen>
</resources>
<?pxml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="px1">3.375px</dimen>
<dimen name="px2">6.75px</dimen>
<dimen name="px3">10.125px</dimen>
<dimen name="px4">13.5px</dimen>
......
<dimen name="px1397">4714.875px</dimen>
<dimen name="px1398">4718.25px</dimen>
<dimen name="px1399">4721.625px</dimen>
<dimen name="px1400">4725px</dimen>
</resources>
你没看错,就是 px,这样我们可以直接用 px 来写布局文件了,而不用对着设计图去换算了,而且我们既然可以将 480x320 的分辨率作为基准,那么同样也可以以我们的设计图的分辨率作为基准,比如我是以 1280x720 作为基准的,只要比例不变就行了,如果以 1280x720 为基准,那么 values-1920x1080 的 dimens 则应该是:
<?pxml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="px1">1.5px</dimen>
<dimen name="px2">3px</dimen>
<dimen name="px3">4.5px</dimen>
<dimen name="px4">6px</dimen>
......
<dimen name="px1397">2095.5px</dimen>
<dimen name="px1398">2097px</dimen>
<dimen name="px1399">2098.5px</dimen>
<dimen name="px1400">2100px</dimen>
</resources>
这样设计图上是多少我们就写多少,再也不用去换算了。
4 dimens 文件生成器
但是这么多 dimens 文件不可能手写,推荐一个 dimens 文件自动生成器:
http://download.csdn.net/download/github_2011/9849086
使用方法:
5 特别适配
有的手机是有虚拟按键的,比如 nexus、华为,这些有虚拟按键的手机,分辨率是将虚拟按键的高度算进去了的,但是 Android 在对 values 适配的时候却不会将虚拟按键的高度算进去,比如一个手机的分辨率本来是 1920x1080,但是虚拟按键栏占了120,那么真实高度就是1800,在适配的时候就不会去找1920x1080了,而是会去找低一级的分辨率了,比如 1280x720了,那么布局又会出问题了,怎么办呢?既然它算的时候就没有算虚拟按键栏的高度,那么我们可以获取虚拟按键栏的高度:
/**
* Description:获取屏幕真实高度(不包括虚拟按键栏)
* Date:2017/9/2
*/
public static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}