一:Android屏幕适配的基本概念介绍
(1)屏幕尺寸
屏幕尺寸:手机对角线的物理尺寸。单位是英寸(inch),1英寸=2.54cm。Android手机常见尺寸5寸、5.5寸、6寸。
(2)屏幕分辨率
屏幕分辨率:手机在横向、纵向的像素点数总和。
px:是屏幕的像素点,1px=1像素点。UI设计师设计图一般会以px作为统一的计量单位。
比如我们的手机分辨率1920*1080,就是长1920个像素,宽1080个像素。
(3)像素密度—DPI
像素密度dpi:指每英寸的像素点数。根据屏幕真实的分辨率和尺寸来计算的。
假设手机每英寸有160个像素,那么该手机的屏幕像素密度是160dpi。
dpi=((像素宽的平方+像素高的平方)(单位是px))然后开根号,除以屏幕尺寸(单位inch)
举个例子:屏幕的分辨率为1920*1080,屏幕尺寸为5寸的时候,那么dpi为440;
(4)密度 dp或dip
dp : 虚拟像素,在不同的像素密度的设备上会自动适配
sp : 同dp相似,还会根据用户的字体大小偏好来缩放
在Android中,手机的分辨率不同,导致同样的尺寸对应不同的像素。反过来,如果我们设置同样的像素大小,那么一个view就会对应不同的尺寸。这样就无法完成屏幕的适配。为了保证同样的单位对应同样的尺寸。我们引入dp这个计量单位。同样的dp,在不同分辨率的手机上,会换算成不一样的像素,相同的尺寸。
在Android中,规定以像素密度160dpi为基准,换算dp和px的数量关系。公式为:px=手机的dpi/160 * dp
比如,在160dpi的手机上,1dp=1px。在320dpi的手机上,1dp=2px。
通过设置dp,这样就可以保证,在不同的手机上,同样的dp对应相同的屏幕尺寸。
(5)屏幕尺寸、分辨率、像素密度三者关系
屏幕像素密度dpi=(√(像素宽的平方+像素高的平方))➗屏幕单线(寸)
density = dpi / 160;
px = density * dp;
如下图:
问题:为什么使用dp还是不能解决屏幕适配的问题
答:
通俗的说:我们适配屏幕的目的,让同样的view在不同的手机屏幕上,占据屏幕的比例是一样的,不是占据相同的尺寸。
通过设置dp可以保证,在不同的手机上,同样的dp对应相同的屏幕尺寸。但是市面上的手机尺寸是不一样的,
这样就导致展示同样的图片,如果这个图片在不同的手机上对应同样的尺寸。那么在小屏手机上,图片可能显示不全。在大屏手机上,会留有空白。
二 :Android屏幕适配
(1)屏幕适配核心思想
在Android代码中,不管在xml布局文件中填写的是什么单位,最后都会被转化为 px;在xml中使用dp,然后dp转化为px。
用dp适配,因为手机尺寸不一样,就导致同样的view,虽然在屏幕的尺寸大小一样,但占据屏幕的比例是不一样的。
所以想要屏幕适配:
我们在xml用dp来设置大小,我们只需要保证所有的手机总dp宽度等于设计稿的宽度。
因为每个手机的px是固定值,根据公式dp=px/density得出来,我们动态的改变density,就能保证所有的手机总宽度dp是相等的。
(2)咱们来说说 density
density 在每个设备上都是固定的,DPI / 160 = density,屏幕的总 dp 宽度=屏幕的总 px 宽度 / density
- 设备 1,屏幕宽度为 1080px,480DPI,屏幕总 dp 宽度为= 1080 / (480 / 160) = 360dp
- 设备 2,屏幕宽度为 1440,560DPI,屏幕总 dp 宽度为 =1440 / (560 / 160) = 411dp
可以看到屏幕的总 dp 宽度在不同的设备上是会变化的,但是我们在布局中填写的 dp 值却是固定不变的
这会导致什么呢?假设我们布局中有一个 View 的宽度为 100dp,
在设备 1 中 该 View 的宽度占整个屏幕宽度的 27.8% (100 / 360 = 0.278)
但在设备 2 中该 View 的宽度就只能占整个屏幕宽度的 24.3% (100 / 411 = 0.243),可以看到这个 View 在像素越高的屏幕上,dp 值虽然没变,但是与屏幕的实际比例却发生了较大的变化,所以肉眼的观看效果,会越来越小,这就导致了传统的填写 dp 的屏幕适配方式产生了较大的误差
这时我们要想完美适配,那就必须保证这个 View 在任何分辨率的屏幕上,与屏幕的比例都是相同的
这时我们该怎么做呢?
A:改变每个 View 的 dp 值?不现实,在每个设备上都要通过代码动态计算 View 的 dp 值,工作量太大
如果每个 View 的 dp 值是固定不变的,那我们只要保证每个设备的屏幕总 dp 宽度不变,就能保证每个 View 在所有分辨率的屏幕上与屏幕的比例都保持不变,从而完成等比例适配,并且这个屏幕总 dp 宽度如果还能保证和设计图的宽度一致的话,那我们在布局时就可以直接按照设计图上的尺寸填写 dp 值
屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度
在这个公式中我们要保证 屏幕的总 dp 宽度 和 设计图总宽度 一致,并且在所有分辨率的屏幕上都保持不变,我们需要怎么做呢?屏幕的总 px 宽度 每个设备都不一致,这个值是肯定会变化的,这时今日头条的公式就派上用场了
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
这个公式就是把上面公式中的 屏幕的总 dp 宽度 换成 设计图总宽度,原理都是一样的,只要 density 根据不同的设备进行实时计算并作出改变,就能保证 设计图总宽度 不变,也就完成了适配
核心代码
核心代码
/**
* 1.获取屏幕宽度
* 2.假设设计图的宽度是360dp,屏幕宽度/360,求得targetDensity,然后设置density。
*/
public static void setCustomDensity(Activity activity, Application application) {
DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
Log.e("appDisplayMetrics", appDisplayMetrics.toString());
int targetDensity = appDisplayMetrics.widthPixels / 360;
int targetDensityDpi = (int) (160 * targetDensity);
appDisplayMetrics.density = appDisplayMetrics.scaledDensity = targetDensity;
appDisplayMetrics.densityDpi = targetDensityDpi;
DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = activityDisplayMetrics.scaledDensity = targetDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}
屏幕适配解决方案:https://github.com/JessYanCoding/AndroidAutoSize/blob/master/README-zh.md
参考文章:
1.今日头条适配方案https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA
三:关于全名屏适配
3.1:关于全名屏,有以下几个名词:沉浸式状态栏、刘海屏、全面屏显示状态栏
3.2:沉浸式真正意义上的理解是:显示全面屏,不显示状态栏
设置状态栏不显示就可以实现全面屏效果。
当没有状态栏的时候,刘海会挡住我们的部分view。大部分的APP是不需要刘海屏适配的。如果刘海挡住的是个按钮,那就影响按钮的操作。这时候要进行刘海屏适配。
3.3:刘海屏的适配目的:就是不要让刘海遮挡到应用程序,或者影响到应用程序的正常使用即可。
如何适配:我们只需要获取刘海屏凹槽的高度就可以了。然后给我们的控件一些偏移量。
3.4:全面屏适配:显示状态栏
全面屏适配就是让布局填满整个屏幕,包括状态栏。但是要显示状态栏。
如何实现:设置状态栏背景色为透明。这样状态栏的背景色就和我们布局的颜色一致了。如果状态栏背景色是浅色的,我们就需要把状态栏的文字颜色设置为黑色。
这样会导致:我们的布局整体上移,所以我们需要获取状态栏的高度。布局要增加margin_top,设置状态栏的高度。