Android 屏幕适配是Android工程师最最头疼的一件事情了。最近公司的项目中就需要引入屏幕适配的工作,但是,UI及尺寸是基于iPhone6的,那么如何做到显示效果上能够更加的接近设计图呢?
下面我将在最小限度的不更改源代码的情况下,使用屏幕分辨率限定符的形式进行Android屏幕的适配方式的介绍
一、 将iPhone6的尺寸与Android sw360dp 进行换算
通常我们需要UI设计基于1920*1080的设计稿,宽度为360dp,将切图的三倍图放置xxhdpi,如果标注是px,那么我们自动除以3作为dp,如果直接是dp那我们直接拿来使用。
| 手机 |
屏幕分辨率 |
宽度DP(heightPixels/density) |
| iPhone6 |
1334*750 |
375pt |
| 小米6 |
1920*1080 |
360dp |
| 华为荣耀8X |
2045*1080 |
360dp |
| 锤子坚果Pro2 |
2070*1080 |
432dp |
假设:UI设计师以iPhone6为基准,标注中有一个为375pt宽的控件,实际像素为750px,如果我们直接用375dp拿到我们Android设备上,则 小米6、华为荣耀8X这两款手机会超出屏幕,而锤子坚果Pro2会小于屏幕,因此如果直接拿到标注进行设置,那么在锤子坚果Pro2手机上所有的控件都会显得比较小,而小米6略显一点大。
实验表明:小米6的控件比设计图大 1-375/360=0.041667,而坚果Pro2比设计图小1-375/432 = 0.131944。
因此我们换算iphone6与我们基准的360dp进行换算,得出更加近似的dp值:
| 手机 |
标注(换算) |
换算公式 |
| iPhone6 |
1pt |
375/375=1 |
| 小米6 |
0.96dp |
360/375=0.96 |
| 华为荣耀8X |
0.96dp |
360/375=0.96 |
| 锤子坚果Pro2 |
1.152dp |
432/375=1.152 |
一、我们先使用Python对1~600常用的数值进行生成
1 2 3 4 5 6 7 8
| from xml.etree import ElementTree as ET if __name__ == '__main__': resources = ET.Element("resources") for i in range(1, 601): dimen = ET.SubElement(resources, "dimen") dimen.attrib = {"name": "pt_" + str(i)} dimen.text = str(round(i * 0.96, 4)) + "dp" ET.ElementTree(resources).write("dimens.xml")
|
dimens.xml
1 2 3 4 5 6 7 8
| <resources> <dimen name="pt_1">0.96dp</dimen> <dimen name="pt_2">1.92dp</dimen> <dimen name="pt_3">2.88dp</dimen> <dimen name="pt_4">3.84dp</dimen> <dimen name="pt_5">4.8dp</dimen> .... </resources>
|
二、将dimens.xml或者里面的dimens复制到Android工程values下
我们可以在此目录下编写我们其他自定义的一些dimens,例如:
1 2 3 4 5 6 7 8
| <resources> .... <item name="main_taotao_scale" format="float" type="dimen">0.244</item> <item name="home_play_scale" format="float" type="dimen">0.25</item> <item name="main_taotao_left_back" format="integer" type="dimen">16</item> <item name="new_main_taotao_left_back" format="integer" type="dimen">24</item> .... </resources>
|
三、正常的使用
在xml布局文件中:
1 2 3 4 5 6 7
| <ImageView android:id="@+id/main_taotao_tell_bac" android:layout_width="@dimen/pt_124" android:layout_height="@dimen/pt_129" android:scaleType="fitXY" android:src="@drawable/main_taotao_tell_bac_phone" app:layout_constraintDimensionRatio="372:387" />
|
在kotlin文件中:
1
| context.resources.getDimension(R.dimen.pt_124)
|
四、屏幕分辨率限定符文件的生产
如果项目已经开发基本完成,不再添加新的dimens值,此时可以生成不同分辨率限定符文件,Python代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from xml.etree import ElementTree as ET import os if __name__ == '__main__': array = [384, 392, 400, 410, 432, 480, 533, 592] for a in array: resources = ET.Element("resources") path = 'values-sw' + str(a) + 'dp' if not os.path.exists(path): os.makedirs(path) for e in ET.parse("dimens.xml").getroot(): dimen = ET.SubElement(resources, "dimen") t = e.text if t[-1] == 'p': dimen.attrib = {"name": e.attrib['name']} dimen.text = str(round(float(t[0:-2]) * a / 360, 4)) + "dp" else: dimen.attrib = {'name': e.attrib['name'], 'format': e.attrib['format'], 'type': e.attrib['type']} dimen.text = str(round(float(t) * a / 360, 4)) ET.ElementTree(resources).write(path + "/dimens.xml")
|
代码中,array数组中的值选取大于360dp,常用的手机就是代码中数组中的值,运行代码后会生成多个values-sw***dp的文件夹:

将这些文件直接复制到Android工程res文件夹下。
适配结束。
五、适配前后对比
设计稿:

适配后(锤子坚果Pro2):

适配前(锤子坚果Pro2):
