Android屏幕适配

Android屏幕适配

dp的问题

unknown_filename
px = dp(dpi/160)

  • dpi是像素密度,指的是在系统软件上指定的单位尺寸的像素数量,它往往是写在系统出厂配置文件的一个固定值。
  • ppi参数,这个在手机屏幕中指的也是像素密度,但是这个是物理上的概念,它是客观存在的不会改变。dpi是软件参考了物理像素密度后,人为指定的一个值,这样保证了某一个区间内的物理像素密度在软件上都使用同一个值。这样会有利于我们的UI适配。
  • 比如,几部相同分辨率不同尺寸的手机的ppi可能分别是430,440,450,那么在Android系统中,可能dpi会全部指定为480。这样的话,dpi/160就会是一个相对固定的数值,这样就能保证相同分辨率下不同尺寸的手机表现一致。
  • 而在不同分辨率下,dpi将会不同,比如:720P中,1dp=2px,1080P中1dp=3px
1080*720 1920*1080
dpi 320 480
dpi/160 2 3

autosize是头条方案,通过反射修改系统的density值

通过dp加上自适应布局和weight比例布局可以基本解决不同手机上适配的问题,这基本是最原始的Android适配方案。
有两个问题:

  1. 只能保证我们写出来的界面适配绝大部分手机,部分手机仍然需要单独适配,为什么dp只解决了90%的适配问题,因为并不是所有的1080P的手机dpi都是480,比如Google 的Pixel2(1920* 1080)的dpi是420,也就是说,在Pixel2中,1dp=2.625px,这样会导致相同分辨率的手机中,这样,一个100dp* 100dp的控件,在一般的1080P手机上,可能都是300px,而Pixel 2 中 ,就只有262.5px,这样控件的实际大小会有所不同。
  2. 开发麻烦,设计稿的宽高往往和Android的手机真实宽高差别极大,以我们的设计稿为例,设计稿的宽高是375px* 750px,而真实手机可能普遍是1080* 1920

适配方法

  1. 宽高限定符适配
    设定一个基准的分辨率,其他分辨率都根据这个基准分辨率来计算,在不同的尺寸文件夹内部,根据该尺寸编写对应的dimens(第没审)文件。
    但是这个方案有一个致命的缺陷,那就是需要精准命中才能适配,比如1920x1080的手机就一定要找到1920x1080的限定符,否则就只能用统一的默认的dimens文件了。而使用默认的尺寸的话,UI就很可能变形,简单说,就是容错机制很差。
  2. smallestWidth适配,或者叫sw限定符适配。
  • Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
    和宽高限定符适配最大的区别在于,前者有很好的容错机制,如果没有value-sw360dp文件夹,系统会向下寻找,比如离360dp最近的只有value-sw350dp,那么Android就会选择value-sw350dp文件夹下面的资源文件。
  • 从开发效率上,它不逊色于上述任意一种方案。根据固定的放缩比例,我们基本可以按照UI设计的尺寸不假思索的填写对应的dimens引用。
  • 我们还有以375个像素宽度的设计稿为例,在values-sw360dp文件夹下的dimens文件应该怎么编写呢?
    这个文件夹下,意味着手机的最小宽度的dp值是360,我们把360dp等分成375等份,每一个设计稿中的像素,大概代表smallestWidth值为360dp的手机中的0.96dp,那么接下来的事情就很简单了,假如设计稿上出现了一个10px * 10px的ImageView,那么,我们就可以不假思索的在layout文件中写下对应的尺寸。
    原生的dp适配可能会碰到Pixel 2这种有些特别的手机需要单独适配,但是在smallestWidth适配中,通过计算Pixel 2手机的的smallestWidth的值是411,我们只需要生成一个values-sw411dp(或者取整生成values-sw410dp也没问题)就能解决问题。

AndroidAutoSize

density 的意思就是 1 dp 占当前设备多少像素
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density (动态)

这个公式就是把上面公式中的 屏幕的总 dp 宽度 换成 设计图总宽度,原理都是一样的,只要 density 根据不同的设备进行实时计算并作出改变,就能保证 设计图总宽度 不变,也就完成了适配。根据宽度适配
density * 屏幕的 dp 宽度= 屏幕的 px 宽度

1
2
3
4
5
<application> 
<meta-data android:name="design_width_in_dp"
android:value="360"/>
<meta-data android:name="design_height_in_dp" android:value="640"/>
</application>

屏幕适配

  • 开发时选取主流屏幕 1280* 720,用相对布局和线性布局
  • 用dp sp不用px,dp单位动态匹配开发后期在不同的分辨率上测试,没有太大问题可以上线
  • 权重适配:weight 只有线性布局有
  • 使用minWidth、minHeight、lines等属性
  • 代码适配:getWindowManager().getDefaultDisplay().getWidth();
  • 如果屏幕的宽高如果屏幕放不下了,可以使用 ScrollView(可以上下拖动)
  • 布局适配:layout-800x180 针对某一种屏幕 工作量大
  • 尺寸适配:dp=px/设备密度=getResource().getDisplayMetrice().dsnsity;根据不同分辨率的屏幕建立不同的valuse,比如valuse-1280x720,values里的dimens里算出dp,最后引用系统会自动匹配。(约等于)320* 240(0.5) 480* 320(1) 480* 800(1.5) 1280* 720(2)就不用布局适配了
  • 在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面。大分辨率图片(单维度超过 1000)大分辨率图片建议统一放在 xxhdpi 目录下管理,否则将导致占用内存成倍数增加。根据当前的设备屏幕尺寸和密度,将会寻找最匹配的资源,如果将高分辨率图片放入低密度目录,将会造成低端机加载过大图片资源,又可能造成 OOM,同时也是资源浪费,没有必要在低端机使用大。
1
2
3
4
5
6
7
8
9
10
11
12
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels; // 屏幕宽度(像素)
int height = metric.heightPixels; // 屏幕高度(像素)
float density = metric.density; // 屏幕密度(0.75 / 1.0 / 1.5)
int densityDpi = metric.densityDpi; // 屏幕密度DPI(120 / 160 / 240)
// px=dp(dpi/160)
float dp = width / (densityDpi / 160);//最大宽度dp
Log.d("HomeActivity", width + "---" + dp + "----" + density + "---" + densityDpi);
// 375
//768---384.0----2.0---320
//1080---540.0----2.75---440

Android屏幕适配
http://peiniwan.github.io/2024/04/7684e624203b.html
作者
六月的雨
发布于
2024年4月6日
许可协议