为什么要做适配?Android碎片化


Android系统碎片化:基于Google原生系统,小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等;
Android机型屏幕尺寸碎片化:5寸、5.5寸、6寸等等;
Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920等

https://screensiz.es/phone 上可以查看市面上流行的手机屏幕尺寸:

基本概念

像素(px)

  • 含义:通常所说的像素,就是CCD/CMOS上光电感应元件的数量,一个感光元件经过感光,光电信号转换,A/D转换等步骤以后,在输出的照片上就形成一个点,我们如果把影像放大数倍,会发现这些连续色调其实是由许多色彩相近的小方点所组成,这些小方点就是构成影像的最小单位“像素”(Pixel)。简而言之,像素就是手机屏幕的最小构成单元。
  • 单位:px(pixel),1px = 1像素点
  • 一般情况下UI设计师的设计图会以px作为统一的计量单位。
  • 像素是绝对单位, 1px就代表固定的尺寸,全天下所有的1px都是一样大的
  • 那么什么是相对单位?比如1%就是相对的

分辨率(横向像素点*纵向像素点)

  • 含义:手机在横向、纵向上的像素点数总和
  • 一般描述成: 宽*高 ,即横向像素点个数 * 纵向像素点个数(如1080 x 1920)。
  • 单位:px(pixel),1px = 1像素点
  • 就相同大小的屏幕而言,当屏幕分辨率低时(例如 640 x 480),在屏幕上显示的像素少,单个像素尺寸比较大。屏幕分辨率高时(例如 1600 x 1200),在屏幕上显示的像素多,单个像素尺寸比较小。

屏幕尺寸(in)

  • 含义:手机对角线的物理尺寸
  • 单位: 英寸(inch,缩写in),一英寸大约2.54cm
  • 常见的屏幕尺寸有4.7寸、5寸、5.5寸、6寸

屏幕像素密度(dpi)

  • 含义:每英寸的像素点数。
  • 例如每英寸内有160个像素点,则其像素密度为160dpi。
  • 单位:dpi(dots per inch)
  • 计算公式: 像素密度 = 像素 / 尺寸 (dpi = px / in)
  • 标准屏幕像素密度(mdpi): 每英寸长度上还有160个像素点(160dpi),即称为标准屏幕像素密度(mdpi)。

xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp

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

注意:屏幕宽度(屏幕尺寸)和像素密度没有任何关联关系,屏幕大不一定就像素密度大,由各大手机厂商自己生产决定。

一部手机的分辨率是宽像素点个数x高像素点个数,屏幕大小是以寸为单位,那么三者的关系是:

举个例子,假设一部手机的分辨率是1080x1920(px),屏幕大小是5寸,问密度是多少?

密度无关像素(dp或dip)

  • 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关
  • 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果,是安卓特有的长度单位。
  • 场景例子:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。
  • dp与px的转换:控件显示像素(px) = 控件相对尺寸(dp) * 设备屏幕的像素密度(dpi)/基准像素密度(dpi),这里基准像素密度选择160dpi。
    即:px = density * dp = (dpi / 160) * dp、density = dpi / 160
  • 320* 480的屏幕,按照google标准dpi=160,则:1dp = 1px, 160dp =160px
    如果是相同大小的屏幕,分辨率改为:640*960,则:160dp = 320px

对于五种主流的像素密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)应按照 2:3:4:6:8 的比例进行缩放

dp(dip)与dpi的区别

dp是density-independent pixel,密度无关像素
dpi是dots per inch,屏幕像素密度

既然用了dp,那为什么还要适配?

比如美工在1280 * 1920分辨率的画布上标注一张图片的宽是30px,那么我们在程序中应该写多少dp的宽度?
按照google官方标准1280*1920分辨率是属于480dpi,density=3,所以30px=10dp,那么我们在程序中应该写10dp的宽度就可以了吗?是不可以的,因为市面上的手机太多了,同样的分辨率的手机屏幕尺寸却千差万别,这样写可能在5inch的手机屏幕上显示效果和UI图上的效果一样,但是在3inch或者6inch手机上的显示效果就会和UI图上的效果差别很大,所以要做适配(也就是说如果各个手机厂商都按照google官方标准,多大分辨率就对应相应规定多大的手机屏幕尺寸,那么我们就不用适配了,直接写换算后的dp值就可以了!)。

那既然用dp也要适配,为什么不直接用px?
因为dp是密度无关像素,320 * 480的屏幕上160dp=160px,如果屏幕大小不变,分辨率改为:640 * 960,则160dp=320px,我们只需要适配dp就可以了!

dp解决了同一数值在不同分辨率中展示相同尺寸大小的问题(即屏幕像素密度匹配问题),但却没有解决设备尺寸大小匹配的问题(即屏幕尺寸匹配问题),可以通过屏幕适配方案解决。

独立比例像素(sp)

  • 含义:scale-independent pixel,叫sp或sip
  • 单位:sp,字体大小专用单位
  • Android开发时用此单位设置文字大小,可根据字体大小首选项进行缩放,在安卓手机系统设置调节字体大小的时候,文字跟随改变。
  • 推荐使用12sp、14sp、18sp、22sp作为字体大小,不推荐使用奇数和小数,容易造成精度丢失,12sp以下字体太小

sp 与 dp 的区别

  • dp只跟屏幕的像素密度有关;
  • sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。

获取屏幕密度

获取屏幕的density值:

系统最终绘制视图控件时都是通过下面这个方法把dp转换成px进行绘制的:

开发者在xml中写视图控件的大小时使用的都是dp,而不用px,因为最后界面在展示的时候都会转化为px绘制在屏幕上,如果你将一个view的宽设为30px,在横向分辨率为300px的手机上占屏幕的1/10,在横向分辨率为480px的手机上这个view占1/16,而如果使用dp来做单位,dp会根据手机屏幕的density(density=dpi/160)自动做调整,转换为不同大小的px,同样大小的dp,大屏幕上是大px,小屏幕上是小px。

适配的几个方面

屏幕适配问题的本质是使得布局、布局组件在不同物理尺寸、不同分辨率的Android手机上具备相同的显示效果,下面我将分几个方面来谈谈如何去适配。

  • 布局组件的适配
  • 布局的适配
  • 代码适配: 即接口适配,加载图片的时候,请求图片时附带图片宽高参数,后台返回对应宽高的图片,而不是用到很小的一张图片却请求了很大的一张图,这样会导致很高的流量使用量。

布局组件的适配

指适配布局组件的大小。

  • 使用密度无关像素(dip、dp)指定尺寸
  • 使用相对布局或线性布局,不要使用绝对布局
  • 使用wrap_content、match_parent、权重
  • 使用minWidth、minHeight、lines等属性
  • dimens使用(根据限定符去找适合的values文件夹下的dimens.xml文件,比如values-sw320dp、values-sw600dp、values-sw720dp)


更多限定符参考:
https://developer.android.google.cn/guide/topics/resources/providing-resources.html

布局的适配

指去适合的布局文件夹下找合适的布局文件。

  • 使用Size限定符
  • 最小宽度限定符
  • 使用屏幕方向限定符
  • 使用布局别名
  • 多套layout适配

图片的适配

  • LOGO 图标

  • 普通图片和图标
  • 自动拉伸位图:Nine-Patch的图片类型
  • 动画、自定义view、shape:一些背景可以用自定义view、shape

ImageView的ScaleType适配

  • android:scaleType=“center”
    保持原图的大小,显示在ImageView的中心。当原图的size大于ImageView的size时,多出来的部分被截掉

  • android:scaleType=“center_inside”
    以原图正常显示为目的,如果原图大小大于ImageView的size,就按照比例缩小原图的宽高,居中显示在ImageView中。如果原图size小于ImageView的size,则不做处理居中显示图片

  • android:scaleType=“center_crop”
    以原图填满ImageView为目的,如果原图size大于ImageView的size,则与center_inside一样,按比例缩小,居中显示在ImageView上。如果原图size小于ImageView的size,则按比例拉升原图的宽和高,填充ImageView居中显示

  • android:scaleType=“matrix”
    不改变原图的大小,从ImageView的左上角开始绘制,超出部分做剪切处理

  • androd:scaleType=“fit_xy”
    把图片按照指定的大小在ImageView中显示,拉伸显示图片,不保持原比例,填满ImageView.

  • android:scaleType=“fit_start”
    把原图按照比例放大缩小到ImageView的高度,显示在ImageView的start(前部/上部)

  • android:sacleType=“fit_center”
    把原图按照比例放大缩小到ImageView的高度,显示在ImageView的center(中部/居中显示)

  • android:scaleType=“fit_end”
    把原图按照比例放大缩小到ImageView的高度,显示在ImageVIew的end(后部/尾部/底部)

刘海屏

google官方刘海屏适配方案
https://developer.android.com/reference/android/view/DisplayCutout

各大厂商的方案
华为: https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114
OPPO: https://open.oppomobile.com/service/message/detail?id=61876
vivo: https://dev.vivo.com.cn/doc/document/info?id=103

折叠屏

华为: https://developer.huawei.com/consumer/cn/devservice/doc/90101

适配方案

AndroidAutoLayout

宽高限定符适配

smallestWidth限定符适配

今日头条屏幕适配方案

github地址

https://github.com/JessYanCoding/AndroidAutoSize
https://github.com/JessYanCoding/AndroidAutoSize/blob/master/README-zh.md

使用

1.添加Gradle配置

implementation 'me.jessyan:autosize:1.2.1'

2.添加AndroidManifest配置

<manifest><application>            <meta-dataandroid:name="design_width_in_dp"android:value="360"/><meta-dataandroid:name="design_height_in_dp"android:value="640"/>           </application>
</manifest>

demo:
https://github.com/JessYanCoding/AndroidAutoSize/tree/master/demo/src/main/java/me/jessyan/autosize/demo

原理解释1

适配思路
当我们在屏幕上看到view的时候,系统会根据程序员设置的view的dp和手机屏幕的dpi计算出view的px,px是多少view就是多大,现在我们需要适配多种屏幕,最终目的就是使view和屏幕的比例都一样,屏幕的px是厂商固定好的,我们只有改变view计算后显示的px值来保证他们的比例都一样。

实现思路
现在就要考虑如何改变系统最后计算出的px了,px=density*dp,系统是根据这个公式去计算view显示的px的,如果在代码中动态的改变每个view的dp,我们可以实现适配,工作量太大,不现实,那么我们只有改变density的值了,
density解析:density在每个设备上都是固定的,density=dpi/160,意思就是1dp占多少像素,这个值是可以在代码中改变的,今日头条屏幕适配方案就是改变系统的density值。

最终方案
那么我们该考虑如何改变density的值,让他最后计算出来的px是我们想要的px呢,如果我们的设计图宽度是360dp,屏幕宽的px是720px,现在我们在设计图上有一个宽180dp的view(即占屏幕的一半),适配后实际显示的px应该应该是360px,density=px/dp=720px/360dp=2;这个2就是我们在这个宽的px=720的设备上计算出来的density,通过屏幕宽的px/设计图宽的dp来动态的改变每个手机设备的density,从而改变系统最后计算出来各个视图控件的px。

原理解释2

今日头条屏幕适配方案的核心原理在于,根据以下公式算出 density:
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density

density 的意思就是 1 dp 占当前设备多少像素

然后把计算出来的density设置为系统的density。

为什么要算出 density,这和屏幕适配有什么关系呢?

//TypedValue.javapublic static float applyDimension(int unit, float value, DisplayMetrics metrics) {switch (unit) {case COMPLEX_UNIT_PX:return value;case COMPLEX_UNIT_DIP:return value * metrics.density;case COMPLEX_UNIT_SP:return value * metrics.scaledDensity;case COMPLEX_UNIT_PT:return value * metrics.xdpi * (1.0f/72);case COMPLEX_UNIT_IN:return value * metrics.xdpi;case COMPLEX_UNIT_MM:return value * metrics.xdpi * (1.0f/25.4f);}return 0;}

大家都知道,不管你在布局文件中填写的是什么单位,最后都会被转化为 px,系统就是通过上面的方法,将你在项目中任何地方填写的单位都转换为 px 的。

所以我们常用的 px 转 dp 的公式 dp = px / density,就是根据上面的方法得来的,density 在公式的运算中扮演着至关重要的一步。

要看懂下面的内容,还得明白,今日头条的适配方式,今日头条适配方案默认项目中只能以高或宽中的一个作为基准,进行适配,为什么不像 AndroidAutoLayout 一样,高以高为基准,宽以宽为基准,同时进行适配呢?

因为大部分市面上的 Android 设备的屏幕高宽比都不一致,特别是现在大量全面屏的问世,这个问题更加严重,不同厂商推出的全面屏手机的屏幕高宽比都可能不一致。

这时我们只以高或宽其中的一个作为基准进行适配,就会有效的避免布局在高宽比不一致的屏幕上出现变形的问题。

明白这个后,我再来说说 density,density 在每个设备上都是固定的,dpi / 160 = density,屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度。

假设有两个设备:

  • 设备 1,屏幕宽度为 1080px,480DPI,屏幕总 dp 宽度为: 1080 / (480 / 160) = 360dp
  • 设备 2,屏幕宽度为 1440px,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 在任何分辨率的屏幕上,与屏幕的比例都是相同的。

这时我们该怎么做呢?改变每个 View 的 dp 值?不现实,在每个设备上都要通过代码动态计算 View 的 dp 值,工作量太大

如果每个 View 的 dp 值是固定不变的,那我们只要保证每个设备的屏幕总 dp 宽度不变,就能保证每个 View 在所有分辨率的屏幕上与屏幕的比例都保持不变,从而完成等比例适配,并且这个屏幕总 dp 宽度如果还能保证和设计图的宽度一致的话,那我们在布局时就可以直接按照设计图上的尺寸填写 dp 值。

屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度

在这个公式中我们要保证 屏幕的总 dp 宽度设计图总宽度 一致,并且在所有分辨率的屏幕上都保持不变,我们需要怎么做呢?屏幕的总 px 宽度 每个设备都不一致,这个值是肯定会变化的,这时今日头条的公式就派上用场了

当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density

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

动态权限适配

  • 权限分类
    Normal Permissions
    Dangerous Permission
  • 查看命令
    adb shell pm list permissions -d -g
  • 注意不能在进入app时就把app用到的所有权限一次性全部申请下来,因为用户在使用app过程中可能关闭动态权限,这样到具体用到权限的页面时还是要写一遍权限申请流程。

参考 :
https://developer.android.google.cn/training/multiscreen/screendensities#java

http://developer.android.com/guide/practices/screens_support.html
https://developer.android.google.cn/guide/practices/screens_support.html

Android 屏幕适配:最全面的解决方案
安卓屏幕完美适配方案——独家秘笈
Android 屏幕适配方案

今日头条适配方案官方文档:一种极低成本的Android屏幕适配方式

骚年你的屏幕适配方式该升级了!-今日头条适配方案
骚年你的屏幕适配方式该升级了!-SmallestWidth 限定符适配方案
今日头条屏幕适配方案终极版正式发布!

Android性能优化—屏幕适配方案相关推荐

  1. 《转》Android 今日头条屏幕适配方案终极版正式发布!

    概述 Android系统发布十多年以来,关于Android的UI的适配一直是开发环节中最重要的问题,但是我看到还是有很多小伙伴对Android适配方案不了解. 刚好,近期准备对糗事百科Android客 ...

  2. 2021年最详细的Android屏幕适配方案汇总

    1 Android屏幕适配的度量单位和相关概念 建议在阅读本文章之前,可以先阅读快乐李同学写的文章<Android屏幕适配的度量单位和相关概念>,这篇文章包含了阅读本文的一些基础知识,推荐 ...

  3. 史上最全Android性能优化方案解析

    Android中的性能优分为以下几个方面: 布局优化 网络优化 安装包优化 内存优化 卡顿优化 启动优化 -- 一.布局优化 布局优化的本质就是减少View的层级.常见的布局优化方案如下: 在Line ...

  4. Android高手笔记-屏幕适配 UI优化

    Android高手笔记-屏幕适配 & UI优化 屏幕与适配 由于Android碎片化严重,屏幕分辨率千奇百怪,而想要在各种分辨率的设备上显示基本一致的效果,适配成本越来越高: 屏幕适配究其根本 ...

  5. android 最新头条适配,今日头条屏幕适配方案终极版正式发布!

    以下是 骚年你的屏幕适配方式该升级了! 系列文章,欢迎转发以及分享: 前言 我在前面两篇文章中详细介绍了 今日头条适配方案 和 SmallestWidth 限定符适配方案 的原理,并验证了它们的可行性 ...

  6. android屏幕适配教程,Android屏幕适配方案,android屏幕适配

    Android屏幕适配方案,android屏幕适配 文章转载禁止用于商业用途,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处莫高雷草原以及作者@JiongBull. Android屏幕适配方 ...

  7. Android性能优化的5种方案

    指标 量化性能的指标有很多,但最重要的就是以下5种: 包大小 响应时间 内存 CPU 耗电量 优化性能就是可以从以上5点入手. 包大小优化 顾名思义就是减少apk包体积大小,apk大小主要取决于res ...

  8. Android屏幕适配方案

    一. 手机适配的应用和使用场景 使android应用程序适用于不同的国家语言.型号.尺寸和SDK版本等手机环境中,其主要功能和界面风格保持不变. 手机适配主要包括三个方面:语言适配.屏幕适配.SDK平 ...

  9. Android 屏幕适配方案(七)

    原文地址为: Android 屏幕适配方案(七) 一. 手机适配的应用和使用场景 使android应用程序适用于不同的国家语言.型号.尺寸和SDK版本等手机环境中,其主要功能和界面风格保持不变. 手机 ...

最新文章

  1. 结合MSDN理解windows service 服务安装的三个类。
  2. 上班上累了,辞职做全职网红!马斯克语出惊人...
  3. Linux服务器安全简明指南
  4. c++求矩阵的秩_一文搞定矩阵相关概念 使用Excel矩阵计算不用愁
  5. 计算机视觉基础:图像处理Task01-图像插值算法
  6. 实践出真知--ZAC《网络营销实战密码》
  7. python入门安装
  8. CAD arx常用函数
  9. 飞利浦css5530+g评测,飞利浦这套入门家庭影院CSS5530竟毫不逊色于自家旗舰!
  10. LINUX中安装gotop检测页面
  11. 外卖cps返利定制开发源码平台小程序美团饿了么红包电影票券分销
  12. python程序-小说下载
  13. ear的英语怎么念_高中英语快速记忆法有哪些?
  14. JsDelivr CDN缓存刷新工具-缓存清除-缓存更新
  15. android可看电视吗,不要VIP也能看电影,安卓手机这4款APP太赞了!
  16. 房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文
  17. 用Android和IOT检测地震波
  18. 美国的做法致芯片市值持续暴跌5000亿美元,美国芯片则祈求中国买更多芯片
  19. 北大c语言百度云资源,北大C语言讲义.pdf
  20. 留给我们的时间不多了,地球不能再热了!

热门文章

  1. el-select下拉框可输入
  2. 把 ChatGPT 微信机器人一键部署到免费服务器!
  3. ps中定义画笔和图案
  4. ESP32-S2与ESP32和ESP8266对比
  5. 点融支付系统架构的演进
  6. Android-高级-UI-进阶之路-(七)-SVG-基础使用-+-绘制中国地图
  7. Python基础系列教程 第一节 安装运行Python
  8. 【C#】C#使用Microsoft.Office.Interop.Word操作Word文档,替换文本
  9. git冲突解决(命令行)大全CTMD
  10. android照片苹果手机图片,不必羡慕安卓党,get这四个iPhone手机拍照技巧,你也能拍出好照片...