Android基础之屏幕适配

一: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,设置状态栏的高度。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值