美文网首页Android进阶
Android 屏幕适配方案

Android 屏幕适配方案

作者: 陆陆陆陆_9d5f | 来源:发表于2019-07-21 16:42 被阅读0次

前言

由于我之前是在一些设备原厂工作的只需要负责sdk的工作以及去给客户驻点开发的,基本不会涉及到屏幕适配,就算是客户那边也是固定的一个Android设备不需要适配;随着我离职之后去面试别的公司,人家一问到我屏幕适配时候我回答不出来,故此我花了些时间研究网上所说的屏幕适配,然后我总结借鉴了一下。

屏幕分辨率限定符与 smallestWidth 限定符适配原理

屏幕分辨率限定符适配原理

屏幕分辨率限定符适配需要在 res 文件夹下创建各种屏幕分辨率对应的 values-xxx 文件夹,如下图:

这样设计图里面显示多少px就可以这么写@dimen/x720或者@dimen/y720,相应的屏幕配比会自动加载相应配比的资源文件,

UI设计的尺寸是多少那就按照那个比例为基准生成对应的资源,比如UI给的是720*1280的(这个单位是px,dpi=160) 然后我就会以那个为基准生成一套资源文件

代码在MakeXml,然后UI设计上标志是多少px,在资源引用时候就使用多少px

缺点:这个方案缺点很明显,只适用常规的手机屏幕尺寸。

这个方案的还有鸿洋老铁的https://blog.csdn.net/lmj623565791/article/details/45460089

效果图:

320*480 576*1027 720*1280

smallestWidth 限定符 适配原理

smallestWidth 限定符适配原理与屏幕分辨率限定符适配原理一样,系统都是根据限定符去寻找对应的 dimens.xml 文件。例如程序运行在最小宽度为 360dp 的设备上,系统会自动找到对应的 values-sw360dp 文件夹下的 dimens.xml 文件。区别就在于屏幕分辨率限定符适配是拿 px 值等比例缩放,而 smallestWidth 限定符适配是拿 dp 值来等比缩放而已。需要注意的是“最小宽度”是不区分方向的,即无论是宽度还是高度,哪一边小就认为哪一边是“最小宽度”。如下分别为最小宽度为 360dp 与最小宽度为 640dp 所对应的 dimens.xml 文件:

获取设备最小宽度代码为:

DisplayMetrics dm = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(dm);

int heightPixels = ScreenUtils.getScreenHeight(this);

int widthPixels = ScreenUtils.getScreenWidth(this);

float density = dm.density; float heightDP = heightPixels / density;

float widthDP = widthPixels / density;

float smallestWidthDP;

if(widthDP < heightDP) {

    smallestWidthDP = widthDP;

}else {

    smallestWidthDP = heightDP;

}

ScreenUtils——>ScreenUtils

使用步骤

1、以设计图最小宽度(单位为 dp)作为基准值,生成所有设备对应的 dimens.xml 文件

    这个可以使用工具ScreenMatch工具,具体怎么使用我这里就不解释了,网上很多资料

2、根据设计图标注,在布局写上对应的值。

设计图标注多少 dp,布局中就写多少 dp ,非常方便!

如果需要动态设置尺寸

/*获取sp值*/

float pxValue = getResources().getDimension(R.dimen.sp_15);//获取对应资源文件下的sp值

int spValue = ConvertUtils.px2sp(this, pxValue);//将px值转换成sp值

mTvShowParams.setTextSize(spValue);//设置文字大小 /*获取dp值*/

float pxValue2 = getResources().getDimension(R.dimen.dp_360);//获取对应资源文件下的dp值

int dpValue = ConvertUtils.px2dp(this, pxValue2);//将px值转换成dp值

使用步骤总结

说了这么多,其实只需要简单的 2 步:

以设计图最小宽度(单位为 dp)作为基准值,利用插件生成所有设备对应的 dimens.xml 文件

根据设计图标注,标注多少 dp,布局中就写多少dp,格式为@dimen/dp_XX。(注意:UI给到的图如果是px单位的话你就得换算成dp单位的,例如:UI给的是1920*1080 单位是px然后你问清楚这个是对应320dp*480dp的屏幕还是哪一款,最后是根据那个dp来标注的,个人理解,比如我那个“益糯健康这个控件距离顶部是126px,但是以dp标记缺失63dp”

缺点:宽度可以适配了但是高度没办法,

距离底部变长了

ConstraintLayout新布局 具体鸿洋老铁

鸿洋 AutoLayout全新的适配方式 堪称适配终结者

AutoLayout我就不介绍了  原文肯定讲的更好听

今日头条适配方案

因为Android中的dp在渲染前会将dp转换成px,计算公式:

px = density * dp;

density = dpi/160;

px = dp * (dpi/160);

屏幕尺寸、分辨率】像素密度三者关系

举个例子:屏幕分辨率为:1920*1080,屏幕尺寸为5吋的话,那么dpi为440。

这样会遇到一些问题:假设我们UI设计图是按屏幕宽度为360dp来设计的,那么在上述设备上,屏幕宽度其实为1080/(440/160)=392.7dp,也就是屏幕是比设计图要宽的。这种情况下, 即使使用dp也是无法在不同设备上显示为同样效果的。 同时还存在部分设备屏幕宽度不足360dp,这时就会导致按360dp宽度来开发实际显示不全的情况。

而且上述屏幕尺寸、分辨率和像素密度的关系,很多设备并没有按此规则来实现, 因此dpi的值非常乱,没有规律可循,从而导致使用dp适配效果差强人意。

所以我们得从dp和px的转换公式 :px = dp * density 入手

可以看出,如果设计图宽为360dp,想要保证在所有设备计算得出的px值都正好是屏幕宽度的话,我们只能修改 density 的值。

通过阅读源码,我们可以得知,density 是 DisplayMetrics 中的成员变量,而 DisplayMetrics 实例通过Resources#getDisplayMetrics可以获得,而Resouces通过Activity或者Application的Context获得。

先来熟悉下 DisplayMetrics 中和适配相关的几个变量:

DisplayMetrics#density 就是上述的density

DisplayMetrics#densityDpi 就是上述的dpi

DisplayMetrics#scaledDensity字体的缩放因子,正常情况下和density相等,但是调节系统字体大小后会改变这个值

所以我们完全可以修改DisplayMetrics的相关数据来解决问题,

具体使用看UI给的是尺寸  我这边的例子是1280*800然后dpi为160的

剩下的就是根据设计图上面的标注的距离和字体直接填写就好了,

不过注意调用前是在setContentView()前调用

Density.setDensity(this);

Density.setDefault(this);

具体代码demo

具体我借鉴的原文在这  ——字节跳动

其实适配还有很多,这些只是我使用过的,具体呢都是使用步骤,你们要是想了解更实际的得自己深究了

相关文章

网友评论

    本文标题:Android 屏幕适配方案

    本文链接:https://www.haomeiwen.com/subject/vpmzqctx.html