摩客怎么设置安卓的dp_Android屏幕适配——使用 dp 实现完美适配
我们一直知道 Android 可以使用 dp、sp 完成简单的适配,那你真的理解了么?先来看几个问题:
dp 是如何进行适配的?
dp 和 px 是如何换算的?
sp 和 dp 的区别?
dp 适配为什么会有偏差?
如何解决 dp 适配的偏差,达到完美适配?
下面我们就来看下源码,解决这些问题。
概述
在 android.util 包下,有个重要的类就是 DisplayMetrics,它主要是记录显示县官的一些信息,比如大小,密度,缩放系数等等。
如果要想获取到其中的信息很简单,可以通过上下文去拿,例如:
DisplayMetrics dm = context.getResources().getDisplayMetrics();
或者按照源码注释上的示例:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
这个类有一大坨常量:
public static final int DENSITY_LOW = 120;
public static final int DENSITY_MEDIUM = 160;
public static final int DENSITY_TV = 213;
public static final int DENSITY_HIGH = 240;
public static final int DENSITY_260 = 260;
public static final int DENSITY_280 = 280;
public static final int DENSITY_300 = 300;
public static final int DENSITY_XHIGH = 320;
public static final int DENSITY_340 = 340;
public static final int DENSITY_360 = 360;
public static final int DENSITY_400 = 400;
public static final int DENSITY_420 = 420;
public static final int DENSITY_440 = 440;
public static final int DENSITY_XXHIGH = 480;
public static final int DENSITY_560 = 560;
public static final int DENSITY_XXXHIGH = 640;
其实最基本的只有DENSITY_LOW、DENSITY_MEDIUM、DENSITY_HIGH、DENSITY_XHIGH、DENSITY_XXHIGH、DENSITY_XXXHIGH,这些都是标准的、主要DPI,其它的都是为了适配引申出来的次要的、介于两者之间的DPI。
DPI 就是 dots-per-inch,每一英寸的像素点。
还有个概念是 PPI,全称是 pixel-per-inch,DPI 和 PPI 是两个不同的概念,即便它们的值有时是一样的,区别嘛...很难描述,大家自己找下资料,这里提到的目的是,有些博客把这两个概念混为一谈是不正确的。
这里主要为大家解读三个参数:
densityDpi:设备的DPI,也就是上面那些常量值,是由手机厂商设置的。
density:缩放系数,这个下面会详细讲解。
scaledDensity:字体缩放系数,和density一样,不过可以受用户设置的字体大小的偏好进行调整。
基础知识
我们先来看下这几个值的赋值,我们发现一个方法,看名字应该是设置默认值。
public void setToDefaults() {
...
density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
densityDpi = DENSITY_DEVICE;
scaledDensity = density;
...
}
1. densityDpi
先从最简单的下手:
public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
public static int DENSITY_DEVICE = getDeviceDensity();
private static int getDeviceDensity() {
return SystemProperties.getInt("qemu.sf.lcd_density",
SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
}
上面代码很好理解,densityDpi 就是从系统属性取值,如果qemu.sf.lcd_density 的值取不到,就取 ro.sf.lcd_density的,还取不到,就使用默认值,也就是 160 了。
qemu.sf.lcd_density 和 ro.sf.lcd_density,手机厂商会写到系统属性中,这样一来,开发者就可以很方便的获取到设备真是的 DPI 了。
2. DENSITY_DEFAULT
这个还是有必要提一句,不要被名字蒙蔽了,它不仅仅是默认值这么简单!
/**
* The reference density used throughout the system.
*/
public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
注释很重要!!!
注释很重要!!!
注释很重要!!!
整个系统使用的参考密度,这个可以理解为基准,后面计算 density 的缩放系数,都是以它为基准的。
3. density
用 DPI 除以基准 DPI,得到的就是density(缩放系数)。
density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
那么应该如何理解呢?
如果一个 160dpi 的设备,那么 density 就是 1。
如果一个 120dpi 的设备,那么 density 就是 0.75。
如果一个 240dpi 的设备,那么 density 就是 1.5。
还不理解?
在 1 英寸内有 160 像素点的设备上,缩放系数就是 1。
在 1 英寸内有 120 像素点的设备上,缩放系数就是 0.75。
在 1 英寸内有 240 像素点的设备上,缩放系数就是 1.5。
4. scaledDensity
与 density 一样的,也是缩放系数,默认情况和 density 的值是相等的。
scaledDensity = density;
与 density 的区别是,scaledDensity 会受用户设置显示字体的大小进行缩放。
上面几个关键概念理解清楚了,下面就要说下,如何使用dp和sp完成屏幕的适配了。
dp 和 sp 是如何适配的
1. dp
dp 是 Android 中的一个适配的单位,用来表示大小。
如果设置控件的高度为 20dp,那么会发生什么?如何在不同设备上进行适配的呢?下面会解答这些问题。
上面讲到的 density(缩放系数) 就派上用场了,通过 dp 值乘以 density 就得到了最终的像素值。
这也就是网上经常流传的换算比例:
在 240 * 320 分辨率,DPI为 120,density 是 0.75,1dp=0.75px。
在 320 * 480 分辨率,DPI为 160,density 是 1,1dp=1px。
在 480 * 800 分辨率,DPI为 240,density 是 1.5,1dp=1.5px。
...
以此类推看下图:
图片来自网络
那么这个DPI是如何计算的?
分辨率为 480*800 的设备举例,在 3.8 寸的屏幕下,DPI 应该约等于 240。
计算公式:
通过公式很容易发现一个问题,DPI 受到分辨率和屏幕尺寸两个值影响的,因为它的定义是,每一英寸的像素点,所以相同分辨率下,不同的屏幕尺寸的设备的 DPI 也是有可能不同的。
这也就说明,Android中我们经常提到的 ldpi,mdpi,hdpi 等等这些规格只能与 DPI 挂钩,并不能由设备分辨率进行区分 ldpi,mdpi,hdpi 这些规格,只能说由于手机尺寸比较接近,大多数的情况下,都符合在上面表格。
知道上面的概念了,这就能理解,在不同DPI设备上 20dp 如何进行适配了。
在 120dpi 的设备上,会乘以 0.75 的缩放系数转换为 15px 展示到界面上。
在 160dpi 的设备上,会乘以 1 的缩放系数转换为 20px 展示到界面上。
在 240dpi 的设备上,会乘以 1.5 的缩放系数转换为 30px 展示到界面上。
...
以此类推,实现了适配。
2. sp
sp 是 Android 中的一个适配的单位,用来表示字体大小。
可以理解为和 dp 是一样的,区别是,它是以 scaledDensity 作为缩放系数,默认情况和 density 的值是一样的,但是在调整系统字体大小时,就会随着字体大小的改变而缩放了。
3. TypedValue
上面我说了,dp、sp 转换 px 会乘以缩放比例,计算出真实的 px 值,口说无凭,来看下 TypedValue 的源码:
public 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;// dp乘以density缩放系数
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;// sp乘以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;
}
如何使用 dp 达到完美适配
理解了这些知识,有什么用?除了面试时可以装一波,更重要的事,可以完善 Android 的 dp 适配机制。
经常使用 dp 适配会发现,只是能达到大致的适配效果,并不完美,会有多个方面造成不准确:
设备厂商设置的 DPI 是否准确。
Android 提供的 DPI 有限,不一定会覆盖到所有设备厂商。
DPI 的计算涉及到分辨率和屏幕尺寸,计算出来的值,都会与系统提供的 DPI 有所偏差。
问题说完了,那么如何利用这套 dp 适配的机制,达到完美适配呢?
density、densityDpi、scaledDensity 这些属性都是可以进行修改的,我们要利用这个搞点事情。
dp 适配偏差都是由于 DPI 不准确,导致 density 缩放系数不准确,出现的问题,如果我们拿到精准的缩放比例,是不是就能将 dp 完美转换为 px 了啊?
我们可以换一下思路,我们要求美工给出一套以 dp 为单位的基准图,例如:基准宽为 320dp,运行在 1080*1920 的设备上。
1. 运行时获取到设备精准的 density
我们可以很轻易的得到缩放系数是 1080 / 320,也就是3.375。
float newDensity = dm.widthPixels / 320;
不要问我,如何在运行时获取到宽高这样的参数,直接看 DisplayMetrics 里面的属性。
/**
* The absolute width of the available display size in pixels.
*/
public int widthPixels;
/**
* The absolute height of the available display size in pixels.
*/
public int heightPixels;
这是就很清晰了吧,有了缩放系数,我们就可以精准的将 1dp 转换为 3.375px 了,达到完美适配。
2. 运行时获取到设备精准的 scaledDensity
得到 newDensity 以后,同样也要获取 newScaledDensity 的值,才能做到对字体 sp 的适配。
float newScaledDensity = newDensity * (dm.density / dm.scaledDensity);
这个还好理解的吧,因为默认状态 density 和 scaledDensity 是相等的,在修改过系统字体大小后,scaledDensity 会进行缩放,所以要将该比例考虑进去。
3. 计算 densityDpi
得到了缩放系数,在设置到 DisplayMetrics 之前,千万不要忘记对 densityDpi 也要进行计算,如果不修改 densityDpi 的话,程序内部计算会出现问题,因为源码中:
density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
所以我们要反向计算出 densityDpi 的值:
int newDensityDpi = (int) (targetDensity * DisplayMetrics.DENSITY_DEFAULT);
4. 设置 DisplayMetrics 参数
终于到了最后一步,修改属性值:
dm.density = newDensity;
dm.scaledDensity = newScaleDensity;
dm.densityDpi = newDensityDpi;
这样,就可以使用 dp 值完美的适配各种屏幕了。
摩客怎么设置安卓的dp_Android屏幕适配——使用 dp 实现完美适配相关推荐
- 摩客怎么设置安卓的dp_Android屏幕适配之单位DP
基本概念 名词概念 名称 解释 px 像素点,一个像素点为1px dp 即dip,像素密度 sp 同dp,但是可以根据系统字体偏好缩放 dpi 每英寸的像素数,也叫做屏幕密度 换算关系 根据换算关系: ...
- 摩客怎么设置安卓的dp_Android中sp和dp区别
--- title: Android中sp和dp区别 date: 2016-09-08 17:04:15 tags: Android categories: Android开发 --- ## 理解an ...
- 摩客怎么设置安卓的dp_Android中的dp
在Android开发中,我们在描述View的宽.高时通常使用dp,但是设计在UI中进行标注时,却使用的是px.所以很多时候就导致UI和实际效果不一致.史记开发中,给设计和开发人员带来了很多困扰. dp ...
- 摩客怎么设置安卓的dp_Android中dp和px之间进行转换
在xml布局文件中,我们既可以设置px,也可以设置dp(或者dip).一般情况下,我们都会选择使用dp,这样可以保证不同屏幕分辨率的机器上布局一致.但是在代码中,如何处理呢?很多控件的方法中都只提供了 ...
- 摩客怎么设置安卓的dp_Android下设置文字大小用sp还是dp
相信很多人看到标题会大吃一惊,长度宽度的数值要用dp,字体的大小用sp,这个理论恐怕在大家心目中早已根深蒂固,官方文档 上也是这样写的 结论: 1.当修改系统字体大小时,字体大小以dp为单位时,大小不 ...
- 摩客怎么设置安卓的dp_安卓屏幕完美适配方案——独家秘笈
一.为什么要适配 由于Android系统的开放性,任何用户.开发者.硬件厂商.运营商都可以对Android系统和硬件进行定制,修改成他们想要的样子. 但是这种"碎片化"到达什么程度 ...
- 摩客怎么设置安卓的dp_摩客【操作攻略】
很多小伙伴都遇到过摩客的困惑吧,一些朋友看过网上零散的摩客的处理方法,并没有完完全全明白摩客是如何解决的,今天小编准备了简单的解决办法,只需要按照 1:如图所示,我们所做的是一个登陆的简单的线框图,现 ...
- 摩客怎么设置安卓的dp_安卓的显示单位dp、dip、px、sp
dp==dip:设备独立像素 .(device independent pixels) dip是年迈的dp,已经退休,在比较老的代码中还可以看到dip.目前谷歌推荐用dp,在我们开发安卓程序的时候,除 ...
- 摩客怎么设置安卓的dp_简单谈谈Android中SP与DP的区别
从一开始写Android程序,就被告知这些常识 一.dp(或者dip device independent pixels) 一种基于屏幕密度的抽象单位.在每英寸160点的显示器上,1dp=1px.不同 ...
最新文章
- 延展信息按单制造ERP荣获2012中国软件优秀解决方案奖
- 网球hcc http catcher使用方法以及规则分享
- 将JPG文件作为EXE执行
- ARM和NEON指令 very gooooooood.............
- 酒店wifi代理服务器没有响应,wn10连接酒店wifi的登录界面无法弹出如何处理
- 前端学习(1411):多人管理31数据分页2
- # 生成单色位二维码图_如何2个小时内学会ps抠图-纯干货
- 基于注解的Spring MVC与JPA如何解决实体的延时加载问题
- python学习之路(10)--难点
- blade利刃出鞘】一起进入移动端webapp开发吧
- 发送需要smtp认证的邮件
- CSS标签选择器→教你如何使用
- Vijos P1423 最佳路线
- 计算机怎么把日历和时间放到桌面上,怎么把日历放到电脑桌面
- 用计算机技术辅助语文教学,利用计算机技术辅助拼音学习“潜力无限”
- php转jsp,阿里西西Html多功能代码转换器(html转js/jsp/php工具)
- CenterNet: Keypoint Triplets for Object Detection论文详解
- 使用CM快速搭建CDH集群
- 数据库事务的四大特性和隔离级别,一文带你看通透
- ktt算法 约化_深度学习面试题
热门文章
- group by内部排序
- 学习HTML简单设计登录网页
- Python 基础学习 locals()用法
- ggplot2箱式图两两比较_如何在ggplot2图形上添加显著性差异注释?
- 【bzoj2563】阿狸和桃子的游戏 脑洞
- RS485接口modbus协议RTU方式
- 如何成为企业急需的技术人才:掌握这些技能,提升你的实力和竞争力
- android小作业,Android studio写的备忘录(记事本)| CSDN打卡
- glPushMatrix()和glPopMatrix()
- 后现代婚礼机器人显神通_预见机器人:各显神通 各国机器人军团炫目来袭(一)...