今日头条屏幕适配深度剖析

基本概念

首先几个基本概念解释:
● dpi:该值代表的是一英寸上有多少个像素点,常见取值为120,160,240。一般这个值才叫做密度

在android里面获取的方法为 metrics.densityDpi;
屏幕尺寸/分辨率得出DPI,一个单位尺寸显示多少像素点。

● density:名字上虽然叫做密度,但是dpi才是密度,这个就叫做density。这个值是一个和标准DPI(默认160dpi后面解释)的比例,一般为 2,1.5 , 1.0,0.75

在android里面获取的方法为 metrics.density;
或者 metrics.densityDpi / 160DPI(标准DPI)

● dp(dip):设备无关像素,系统会自动根据density自动转换为px。
在android里面获取的方法为dp转px公式为

px= dpvalue *metrics.density;
px= dpvalue * (metrics.densityDpi / 160DPI(标准DPI))

● px:代表的是分辨率

这些值上面对应在现实生活中是这几个常用词汇:

● 屏幕尺寸:代表的屏幕宽高信息尺寸(单位cm)
● 屏幕分辨率:代表屏幕宽和高分别有多少像素点(单位px)
● 屏幕密度:代表一个单位屏幕尺寸上显示多少个像素点(单位dpi)

采用PX编写控件宽高尺寸出现的问题

接下来的讲的控件宽高尺寸适配都是用的px单位

为什么出现DPI,不进行直接对屏幕尺寸和分辨率进行适配

可以说我们安卓写控件宽高大小(用px)不需要关心屏幕尺寸也不需要关心分辨率(这样做会累死,因为很多设备虽然屏幕尺寸相同但是分辨率不同或者反过来,不同情况下控件宽高(用px)也不一样,一个个去适配宽高大小太复杂了),所以就需要个东西对尺寸和分辨率都进行考虑。
接着就会发现虽然屏幕尺寸和分辨率都很乱,但是大致上可以找到规律,就是 一个屏幕尺寸上显示多少个像素点主要就四种,所以DPI大体上只有四种,只需要关心这四种DPI就行,不需要陷入到具体的屏幕尺寸和分辨率上。

Android Design [1] 里把主流设备的 dpi 归成了四个档次,120 dpi、160 dpi、240 dpi、320 dpi。

为什么出现density而不是对DPI进行适配

由于市面上的设备DPI不相同,如果不进行DPI适配的话,就会出现大小不一问题

比如在120DPI上(一个屏幕单位显示120个像素点)设计的120px的控件尺寸 在屏幕上显示会占用一个屏幕单位。
跑在240DPI上(一个屏幕单位显示240个像素点),就会只占用0.5个屏幕单位,因此120DPI上跑的所有控件到了240DPI的设备上都会缩小一半。

所以就需要进行适配不同DPI的设备,虽然DPI我们只关心四种,比起适配不同屏幕尺寸和不同分辨率的设备需要适配的工作量大大降低,但是还是需要适配四种也就是四倍的工作量。

安卓的资源目录(图片,布局,drawable等)会带着后缀比如mdpi,xdpi,xxdpi…这些不同的资源目录下面存放着的就是对应DPI设备上使用的资源。

对于图片来说我们不需要关心,让UI去做不同DPI的图就行;但是 对于同一个布局里面的控价宽高尺寸(用px)来说仅仅因为尺寸不一样就需要重新写四套布局吗?UI也需要对每个标注出四套标注吗? 这可是四倍的工作量
所以我们希望可以根据不同DPI去做一个尺寸的比例缩小放大

首先要适配,就需要我们设计图采用一个基准DPI去设计控件尺寸大小,然后在不同DPI的设备上,根据我们设计图用的基准DPI的值 去除以 对应显示设备的DPI,就可以得到我们需要进行缩放的比例了,最后进行对应尺寸X比例即可实现放大缩小在不同DPI的设备上完成适配。

比如如果我们设计图是在120DPI的设备上出的标注,那么上面说的120DPI上跑的120px的控件要在240DPI上采用240PX的控件才可以,可以看到是120*2得出来的;

但是如果要泡在160和320的设备上,对应的比例就可能除不尽导致最后得出的尺寸有小数,不够精准。

所以我们设计图该采用哪种基准DPI进行出标注呢?

我们会发现这四个主流的DPI也有个规律:

如果以 160 dpi 作为基准的话,只要尺寸的 DP 是 4 的公倍数,XHDPI 下乘以 2,HDPI 下乘以 1.5,LDPI 下乘以 0.75 即可满足所有尺寸下都是整数 pixel 。

所以我们默认设计图和我们最终编写 适配的都是在160DPI设备上跑的,不同DPI的设备进行对应的缩放比例调整即可,这个缩放比例就是density。

因为记忆这四个DPI的数值还是比较麻烦,所以我们直接记忆density即可,也就是说我们的控件宽高尺寸X对应的density即可。最后得出的公式就是:
最终显示在不同DPI设备上的控件宽高尺寸 = 160DPI标注图上控件宽高尺寸 X 对应的density(显示设备DPI / 160DPI得出)。

我们只需要根据这个公式就可以计算出不同DPI下的宽高尺寸,但是好像我们并没有解决根本问题,上面说的只是节省了UI的工作量他们不需要出四套不同dpi上不同宽高尺寸的图了,我们还是依然需要写四个不同的布局文件

采用DP编写控件宽高尺寸

接上面说的,我们依然还是需要写四套布局写四个不同的宽高尺寸,如果有个工具可以自动帮我们做转换就好了,我们上面一直说的都是用的px进行的适配,如果我们自定义一个尺寸单位,这个尺寸单位如果在变成px的过程中进行上面我们说的density转换 那么是不是就可以达到我们只写一个布局文件的目的了。

没错,这个单位就是dp,密度无关像素,也就是dpi无关,因为dp最终转换px的时候会进行不同DPI的适配(也就是X对应的density)现在是不是就可以理解为什么叫做密度无关了吧。

这样我们以后编写尺寸都用dp进行编写(采用160DPI的设计图),dp转换为px的时候 乘以 对应设备缩放的density(显示设备DPI/160DPI)即可。

这样在160DPI上采用的dp就是px,因为我们就是在160DPI上出的px标注。
在320dpi上采用的dp最终转换为px的时候会乘以2,因为我们是按照160DPI设计的。
可以看出dp是px的一个封装

国内屏幕参数太乱导致density精度不足导致最终显示有问题

假设宽分辨率1080px,480DPI的设备得出屏幕宽度518400英寸;
另外一个设备分辨率1440px,560DPI的设备得出屏幕宽度806400英寸。

如果一个100dp宽度的控件显示在这两个设备上分别占用300px,350px像素点,对应显示在屏幕上的尺寸分别为0.625英寸,0.625英寸(不同尺寸屏幕 显示的控件尺寸居然一样);
得出对应占用整个屏幕宽度的百分比分别为0.000000121,0.00000078。

我们发现经过系统转换DP为PX,最终占据的px已经经过转换但是 在屏幕上显示的百分比却有问题(从不同屏幕尺寸显示的控件尺寸一样就可以看出不对了),可以发现 根本原因还是分辨率和尺寸太乱了也就是说DPI太乱了,安卓官方想的是主流DPI适配即可 (主流dpi经过160基准DPI的转换因为density都是整数所以都可以正常转换,显示的尺寸比例不同设备也都一样),

但是国内形形色色的手机太多了(转换的density有小数最终转换为px会精度丢失,导致比例不同),官方的适配方案已经在国内不可行了,所以出现了今日头条的方案。

今日头条

根据上面的分析我们已经知道了 官方的density计算方案是设备DPI/基准DPI,但是对于国内来说由于设备DPI太多太乱(屏幕尺寸和分辨率太乱)且没有规律因此导致density精度丢失转换出问题。

我们就需要另外想办法了,像当初dp诞生一样我们在重新创建一个单位进行转换?改动太大且无法兼容;改变每个 View 的 dp 值?不现实,在每个设备上都要通过代码动态计算 View 的 dp 值,工作量太大(这和当初改变每个view的px值思路一样);修改density计算方案看起来可行,因为官方已经有这种转换的机制了我们修改转换机制即可。

如何才能保证不同dpi最终计算出来的density不存在精度丢失问题呢?

之前的办法在于找到DPI之间的比例进行等比缩放,但是DPI太多了比例会丢精度导致数值不精准;既然DPI不固定,我们就找到固定的部分,我们发现我们写的dp是固定的,之前一直迁就设备,主动权在设备上导致我们被动,所以要让主动权在我们手上,我们控件写的dp是固定的,如果可以让所有设备屏幕的总dp都一样是不是也就可以保证比例一样。

我们首先需要让UI出图的标准是根据宽高总DP进行出图,而不是之前的基准160DPI出图,UI出的屏幕宽高DP就是实际的屏幕宽高DP,而屏幕宽高dp=屏幕宽高px(像素)/density,所以我们想要最终的屏幕宽高dp(设计图宽高dp)一样就需要重新计算density也就是:

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

这样动态修改desnity就可以认为所有设备的总dp都和设计图的dp一样了

方案验证

在这里插入图片描述

方案优缺点

优点是一刀切不需要改动density;但是缺点也是这个,由于采用的是让屏幕总dp和设计图dp一样的方案,如果是我们自己写的view那么对应的dp比例就可以正常转换; 但是如果我们用了别人的view,而别人view的dp不是按照我们设计图dp写的并且和我们设计图dp差别很大,就会出现问题。

这就是两个设计图尺寸不一致导致的非常严重的问题,当两个设计图尺寸差距越大,那适配的效果也就天差万别了

方案一

无法让三方库来适应我们项目的设计图尺寸,所以只有我们自身作出修改,去适应三方库的设计图尺寸,我们将项目自身的设计图尺寸修改为这个三方库的设计图尺寸,就能完成项目自身和三方库的适配

方案二

在这里插入图片描述

参考链接

基础概念方面文章:https://blog.csdn.net/qq_30196607/article/details/50803392
https://www.imooc.com/article/260877
头条方案的理解:https://blog.csdn.net/xcbyaya/article/details/137981609

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/32168.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL进阶——视图

目录 1基本语法 1.1创建 1.2 查询 1.3 修改 1.4 删除 2 检查选项 2.1 级联CASCADED 2.2本地LOCAL 3 更新及作用 3.1视图的更新条件 3.2视图的作用 4视图案例 1基本语法 视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&…

Github 2024-06-19 C开源项目日报 Top9

根据Github Trendings的统计,今日(2024-06-19统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目9C++项目1Netdata: 开源实时监控平台 创建周期:4020 天开发语言:C协议类型:GNU General Public License v3.0Star数量:68982 个Fork数量…

乾元通渠道商中标金昌市自然灾害应急能力提升项目

近日,乾元通渠道商中标甘肃省金昌市自然灾害应急能力提升项目,乾元通作为设备厂家,为项目提供通信指挥类装备(多链路聚合设备) QYT-X1 。 随着万亿国债项目的全面铺开, 青岛乾元通数码科技有限公司 作为国家…

STM32多种开发环境及生成hex及bin文件介绍

一.STM32开发环境 KEIL系列 (1)KEIL公司目前有四款独立的嵌入式软件开发工具,即MDK、KEIL C51、KEIL C166、KEIL C251,它们都是KEIL公司品牌下的产品,都基于uVision集成开发环境,其中MDK是RealView系列中…

四边形不等式优化

四边形不等式优化 应用于类似以下dp转移方程。 f i min ⁡ 1 ≤ j ≤ i ( w i , j , f i ) f_{i}\min_{1\le j\le i}(w_{i,j},f_{i}) fi​1≤j≤imin​(wi,j​,fi​) 假设 w i , j w_{i,j} wi,j​ 可以在 O ( 1 ) O(1) O(1) 的时间内进行计算。 在正常情况下,…

Python神经影像数据的处理和分析库之nipy使用详解

概要 神经影像学(Neuroimaging)是神经科学中一个重要的分支,主要研究通过影像技术获取和分析大脑结构和功能的信息。nipy(Neuroimaging in Python)是一个强大的 Python 库,专门用于神经影像数据的处理和分析。nipy 提供了一系列工具和方法,帮助研究人员高效地处理神经影…

【C++实验】多项式加减

题目:一元多项式运算 基本要求: (1) 输入并建立多项式; (2) 输出多项式; (3) 多项式加法 (4) 多项式减法。 测试数据: 代码展示: #i…

[论文阅读笔记31] Object-Centric Multiple Object Tracking (ICCV2023)

最近Object centric learning比较火, 其借助了心理学的概念, 旨在将注意力集中在图像或视频中的独立对象(objects)上,而不是整个图像。这个方法与传统的基于像素或区域的方法有所不同,它试图通过识别和分离图像中的各个对象来进行…

代码随想录——全排列Ⅱ(Leetcode 47)

题目链接 回溯 class Solution {List<List<Integer>> res new ArrayList<List<Integer>>();List<Integer> list new ArrayList<Integer>();boolean[] used;public List<List<Integer>> permuteUnique(int[] nums) {used …

IPD笔记

IPD笔记 先弄一个一图流&#xff0c;改天再过来继续补充 IPD&#xff08;Integrated Product Development&#xff09;即集成产品开发&#xff0c;是一套产品开发的模式、理念与方法。华为的IPD的核心思想是基于市场需求&#xff0c;将产品开发作为一项投资来管理&#xff0c;以…

python pynput实现鼠标点击两坐标生成截图

脚本主要实现以下功能&#xff1a; 按ctrl开始截图&#xff0c;点击两个坐标&#xff0c;保存截图tk输出截图文本信息&#xff0c;文本输出内容倒序处理默认命名为A0自增。支持自定义名称&#xff0c;自增编号&#xff0c;修改自定义名称自增重新计算清空文本框内容 from pyn…

three.js 第十一节 - uv坐标

// ts-nocheck // 引入three.js import * as THREE from three // 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls // 导入lil.gui import { GUI } from three/examples/jsm/libs/lil-gui.module.min.js // 导入tween import * as T…

1931java Web披萨店订餐系统idea开发mysql数据库web结构java编程计算机网页源码servlet项目

一、源码特点 java Web 披萨店订餐系统是一套完善的信息管理系统&#xff0c;结合java 开发技术和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。 视频地址&#xff1a;…

Android CTS环境搭建

CTS即Compatibility Test Suite意为兼容性测试&#xff0c;是Google推出的Android平台兼容性测试机制。其目的是尽早发现不兼容性&#xff0c;并确保软件在整个开发过程中保持兼容性。只有通过CTS认证的设备才能合法的安装并使用Google market等Google应用。 搭建CTS测试环境需…

CST初级教程 七

本教程将实例讲解CST设计优化仿真及其操作步骤。下面是一个微带功率分配器的图片&#xff1a; 一 3D建模 Substrate 建模 Step1 绘制Substrate外形 Substrate 的尺寸参数如下&#xff1a; Step2 添加新材料Substrate Step3 将新建的材料分配给Substrate 选中新建材料Substra…

数学建模系列(3/4):典型建模方法

目录 引言 1. 回归分析 1.1 线性回归 基本概念 Matlab实现 1.2 多元回归 基本概念 Matlab实现 1.3 非线性回归 基本概念 Matlab实现 2. 时间序列分析 2.1 时间序列的基本概念 2.2 移动平均 基本概念 Matlab实现 2.3 指数平滑 基本概念 Matlab实现 2.4 ARIM…

WordPress插件:子比zibll主题插件 炙焰美化全开源插件V3.2

在网络世界中&#xff0c;开源内容管理系统&#xff08;CMS&#xff09;已经成为了网站构建的关键工具之一。WordPress&#xff0c;作为最受欢迎的开源CMS之一&#xff0c;其广泛的应用及其灵活性使得它成为了创建和管理各种类型网站的理想选择。而Zibll主题插件&#xff0c;作…

【Android WebView】WebView基础

一、简介 WebView是一个基于webkit引擎、展现web页面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本内核&#xff0c;4.4后直接使用了Chrome。 二、重要类 以WebView类为基础&#xff0c;WebSettings、WebViewClient、WebChromeClient为辅助共同完成安卓段加…

2024年【T电梯修理】免费试题及T电梯修理考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 T电梯修理免费试题参考答案及T电梯修理考试试题解析是安全生产模拟考试一点通题库老师及T电梯修理操作证已考过的学员汇总&#xff0c;相对有效帮助T电梯修理考试总结学员顺利通过考试。 1、【多选题】TSGT7005-2012《…

【Java】已解决java.nio.channels.ClosedChannelException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.nio.channels.ClosedChannelException异常 在Java的NIO&#xff08;New I/O&#xff09;编程中&#xff0c;java.nio.channels.ClosedChannelException是一个常见的异常…