Android开发-之屏幕适配

Android开发-之屏幕适配

前言

Android 系统能发展到今天,离不开其开源性,但是随着越来越多的设备接入 Android 系统,并对 Android 系统进行各种各样的定制,导致长期以来出现了各种碎片化严重的问题。例如,Android 屏幕尺寸多种多样,如 5 寸、5.5 寸、6 寸、6.4 寸 等等,当然,屏幕分辨率也是多种多样,这很容易导致同一元素在不同手机上显示的效果不同的问题,因此,Android 应用开发中的屏幕适配工作也越来越重要。

本篇文章就介绍一下 Android 中屏幕适配相关的知识。

屏幕适配基本概念

屏幕尺寸

屏幕尺寸是指手机对角线的物理长度,单位是 英寸(inch,1 inch = 2.54 cm),

例如我们常见的 6 英寸手机,表示手机的对角线长度是 6 * 2.54 = 15.24 cm 。
屏幕分辨率
指的是手机在横向、纵向上的像素点数总和,单位是 px(pixel,1 pixel = 1 像素点) ,

分辨率一般描述成 A * B ,例如:1080 * 1920,表示屏幕每一行有 1080 个像素点,每一列有 1920 个像素点。

对于 Android 设备,我们可以通过 ADB 命令快速查看屏幕分辨率信息:

adb shell wm size

屏幕像素密度

指的是每英寸的像素点数量,单位是 dpi(dots per ich),假设设备内每英寸有160个像素,那么该设备的屏幕像素密度为 160 dpi 。

屏幕像素点的计算公式如下:
在这里插入图片描述
即,先用勾股定理计算出对角上的像素点数量,再用该数量除以屏幕尺寸。

例如:4.7 英寸,1080 * 1920 分辨率的手机,它的像素密度为:
在这里插入图片描述
对于 Android 设备,我们可以通过 ADB 命令快速查看屏幕像素密度信息:

adb shell wm density

密度无关像素

密度无关像素,英文名 density-independent pixel,单位 dp,它是 Android 特有的单位,它与设备上的实际物理像素点无关,只与屏幕像素密度有关,它可以保证在不同屏幕像素密度的设备上显示相同的效果。
注意:在 Android 中,1 英寸 = 160 dp 。

为什么要用 dp 而不直接用 px 呢?我们举个简单的例子:

假设需要在屏幕上显示一条长度为屏幕宽度一半的线,用 px 来表示的话,那么:

  • 在分辨率 480 * 800 ,屏幕密度 240 dpi 的设备上(约 3.89 英寸),这条线的长度应该为 240 px
  • 在分辨率 320 * 480 ,屏幕密度 160 dpi 的设备上(约 3.61 英寸),这条线的长度应该为 160 px

对于以上情况,如果使用 px 设置这条线的长度,需要使用两个不同的值才能适配两个不同分辨率的设备。

但如果我们使用 dp 为单位,那么在以上这两种情况,都只需要使用 160 dp 就可以将这条线显示为屏幕一半的长度。

在平时的开发中,UI 设计师给我们的设计图都是以 px 为单位的,而我们则是要使用 dp 作为单位进行开发,因此我们需要将 px 转化为 dp,他们之间的转换关系如下所示:
在这里插入图片描述
在这里插入图片描述
由此可见,在设备屏幕密度为 160 dpi 的情况下,1 dp = 1 px 。

独立比例像素

独立比例像素,英文名 scale-independent pixel,单位 sp,它是 Android 特有的单位,在 Android 中一般用于设置字体大小。

一般来说,1 sp = 1dp 。推荐使用偶数 sp 值设置字体大小,不推荐使用奇数和小数,因为容易造成精度的丢失问题。

屏幕适配方案

dp 原生方案

我们需要思考,Android 使用 dp 究竟解决了什么问题?

在上面 dp 概念的介绍中,我们知道,在 Android 中,1 英寸 = 160 dp

对于相同尺寸,不同分辨率的设备,他们拥有着不同的屏幕像素密度,因此他们每 1 dp 所代表的像素数量是不一样的
如果使用相同的 px 值显示一条线,那么这条线的长度在两个设备上将会显示不同的比例,

如果使用 dp 作为单位,由于每一 dp 它所对应的物理长度是一样的,因此,使用相同的 dp 值,他们的显示的比例是一样的。

实际上,dp 的优势也主要体现在相同尺寸,不同分辨率的设备的适配效果。对于不同尺寸不同分辨率的设备,dp 的适配效果就差强人意了!
举个例子。

假设我们的 UI 设计图是按屏幕分辨率 1080 * 2670,屏幕尺寸为 6 寸的设备(dpi 约为 480)来设计的,则通过计算,UI 图中设备屏幕的最大宽度为 360 dp 。

但是对于屏幕分辨率 1080 * 1920,屏幕尺寸为 5 寸的设备(dpi 约为 440),通过计算,

它的屏幕宽度其实为 1080 / (440/160) = 392.7 dp
也就是屏幕是比设计图要宽的。

这种情况下, 即使使用 dp 也无法在不同设备上显示为同样效果, 同时还存在部分设备屏幕宽度不足 360 dp,这时就会导致按 360 dp 宽度来开发,实际却显示不全的情况。

总结:仅使用 dp 原生方案进行屏幕适配,适配性非常差,不建议使用该方案。

sw 限定符适配方案

sw 限定符适配即 smallestWidth 适配,也叫最小宽度限定符适配。

它的原理是,Android 会识别屏幕可用高度和宽度的最小尺寸的 dp 值,然后根据识别到的结果去 资源文件 中寻找对应限定符的文件夹下的资源文件。其实就是系统通过特定的规则来选择对应的文件。

举个例子。

某手机的屏幕分辨率是 1080 * 1920,屏幕像素密度是 480 dpi,通过计算,
它的最大宽度对应的 dp 值是:1080 / (480 / 160) = 360 dp
根据这个 360 dp 值,系统会去寻找 value-sw360dp 的文件夹以及对应的资源文件并使用它。

如果没有 value-sw360dp 文件夹,系统会向下寻找,比如离 360 dp 最近的只有 value-sw350dp,那么Android就会选择 value-sw350dp 文件夹下面的资源文件。

一般来说,value-swXXXdp 这些文件夹都会创建在 /src/main/res/ 目录下,例如我工程中创建的 value-sw480dp 文件夹:
在这里插入图片描述
在创建这些文件夹前,我们需要提前设置好基准尺寸,一般我们会将 UI 设计图中使用的最大宽度对应的 dp 值来作为基准 dp 值,比如下面我这里将会以 360 dp 作为基准,我们来看看基准资源文件 /src/main/res/value/dimens.xml,如下所示:
在这里插入图片描述

接下来,我们创建一个value-sw480dp 文件夹并在其中创建 dimens.xml 文件:
在这里插入图片描述
那么这份数据是怎么计算得到的呢,当然也是在基准尺寸的基础上计算得到的,
即:dp_2 = (480 / 基准) x 2 = (480 / 360) x 2 = 2.6667 dp
这种适配方案容错率低,其缺点就是侵入性高,且需要根据不同机型的最大宽度 dp 创建多个文件夹,维护成本也比较大。

相比于使用 dp 原生方案,sw 限定符适配方案 显然更加合适。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【新书推荐】7.2 while语句

本节必须掌握的知识点: 掌握if语句语法 熟练使用if语句 7.2.1 示例二十三 ■while语句其语法形式: while(表达式) { 语句块; } ●语法解析: 第一步:执行表达式,如果表达式为真,则执行第…

【代码】Processing笔触手写板笔刷代码合集

代码来源于openprocessing,考虑到国内不是很好访问,我把我找到的比较好的搬运过来! 合集 参考:https://openprocessing.org/sketch/793375 https://github.com/SourceOf0-HTML/processing-p5.js/tree/master 这个可以体验6种笔触…

Netty连接通道中的Channel参数模型

ChannelOption(Channel中的连接参数) ChannelOption.SOBACKLOG ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候&…

P1297 [国家集训队] 单选错位 对期望的理解

[国家集训队] 单选错位 - 洛谷 思路: 其实每个位置的得分只和前一个位置有关。 而他们俩的所有情况的期望就是答案的这部分。 ——这是难想的,我期望学的不好。 (题目给的是每种情况的所有位置的和,全加起来是答案&#xff1…

【数据分享】1929-2023年全球站点的逐月平均风速(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、能见度等指标,说到气象数据,最详细的气象数据是具体到气象监测站点的数据! 有关气象指标的监测站点数据,之前我们分享过1929-2023年全球气象站…

ansible shell模块 可以用来使用shell 命令 支持管道符 shell 模块和 command 模块的区别

这里写目录标题 说明shell模块用法shell 模块和 command 模块的区别 说明 shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等 shell模块用法 ansible slave -m shell -a cat /etc/passwd | grep root # 可以使用管道…

边缘计算初创公司ZEDEDA获7200万美元C轮融资,助力边缘计算市场扩张!

边缘计算领域传来喜讯! 边缘计算社区获悉,就在昨天(2月7日),边缘计算企业ZEDEDA成功募集7200万美元C轮融资,折合人民币高达约5.18亿元。据悉,此次融资使ZEDEDA的估值飙升至4亿美元,相…

Java:内部类、枚举、泛型以及常用API --黑马笔记

内部类 内部类是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。 当一个类的内部,包含一个完整的事物,且这个事物没有必要单独设计时&a…

git flow与分支管理

git flow与分支管理 一、git flow是什么二、分支管理1、主分支Master2、开发分支Develop3、临时性分支功能分支预发布分支修补bug分支 三、分支管理最佳实践1、分支名义规划2、环境与分支3、分支图 四、git flow缺点 一、git flow是什么 Git 作为一个源码管理系统,…

JavaScript鼠标移动事件

🧑‍🎓 个人主页:《爱蹦跶的大A阿》 🔥当前正在更新专栏:《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 鼠标移动是用户界面中非常重要的交互行为。学习区分不同的鼠标移动事…

PySpark(三)RDD持久化、共享变量、Spark内核制度,Spark Shuffle、Spark执行流程

目录 RDD持久化 RDD 的数据是过程数据 RDD 缓存 RDD CheckPoint 共享变量 广播变量 累加器 Spark 内核调度 DAG DAG 的宽窄依赖和阶段划分 内存迭代计算 Spark是怎么做内存计算的? DAG的作用?Stage阶段划分的作用? Spark为什么比MapReduce快? Spa…

机器学习10-特征缩放

特征缩放的目的是确保不同特征的数值范围相近,使得模型在训练过程中更加稳定,加速模型收敛,提高模型性能。具体而言,零均值和单位方差的目标有以下几点好处: 1. 均值为零(Zero Mean)&#xff1a…

红队打靶练习:GLASGOW SMILE: 1.1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 1、gobuster 2、dirsearch WEB web信息收集 /how_to.txt /joomla CMS利用 1、爆破后台 2、登录 3、反弹shell 提权 系统信息收集 rob用户登录 abner用户 penguin用户 get root flag 信息收集…

【Python】使用 requirements.txt 与 pytorch 相关配置

【Python】使用 requirements.txt 与 pytorch 相关配置 前言一、pip1、导出结果含有路径2、导出不带路径的 二、Conda1、导出requirements.txt2、导出yml 文件 三、第三方包:pipreqs(推荐)1、创建并激活conda环境2、安装requirements文件的pi…

Linux进程间通信(2)--System V共享内存 | 消息队列 | 信号量

目录 实现原理 使用系统调用创建共享内存 使用shmget函数创建共享内存: 使用shmat函数将共享内挂接到进程地址空间的共享区 使用shmdt函数取消共享内存与进程地址空间的关联 ​编辑 使用shmctl函数释放共享内存 共享内存的属性 System V消息队列 &#xff…

文件上传-Webshell

Webshell简介 webshell就是以aspphpjsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页木马后门。 攻击者可通过这种网页后门获得网站服务器操作权限,控制网站服务器以进行上传下载文件、查看数据库、执行命令等… 什么是木马 …

docker 基于容器创建本地web容器化镜像

一、docker 基于容器创建本地web容器化镜像 1、启动指定buysbox 镜像 docker run --name b1 -it busybox:latest 2、创建目录&#xff0c;并创建html mkdir -p /data/html vi index.html 内容自定义例如&#xff1a;<h1>welcome to busybox<h1> 3、新增窗口&am…

类和对象 第六部分第二小节:继承方式

前情提要&#xff1a;继承的语法&#xff1a;class 子类 继承方式&#xff1a;父类 继承方式一共有3种&#xff1a; 代码案例&#xff1a; 前置代码 #include<iostream> using namespace std; class Base1 { public:int m_A; protected:int m_B; private:int m_C; };公共…

linux C编程入门

Ubuntu 下也有一些可以进行编程的工具&#xff0c;但是大多都只是编辑器&#xff0c; 也就是只能进行代码编辑&#xff0c;如果要编译的话就需要用到 GCC 编译器&#xff0c;使用 GCC 编译器肯定就 要接触到Makefile。 1&#xff1a;hello world!!! 我们所说的编写代码包括两部…

Qt网络编程-TCP与UDP

网络基础 TCP与UDP基础 关于TCP与UDP的基础这里就不过多介绍了&#xff0c;具体可以查看对应百度百科介绍&#xff1a; TCP&#xff08;传输控制协议&#xff09;_百度百科 (baidu.com) UDP_百度百科 (baidu.com) 需要知道这两者的区别&#xff1a; 可靠性&#xff1a; TC…