Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读

本文详细解释了Android系统中关于屏幕尺寸和密度的概念,包括屏幕尺寸分类(大、正常、小)、长宽比、分辨率和密度。重点介绍了密度无关像素(DIP)的重要性,以及如何通过DIP确保UI在不同密度屏幕上适配。Android将屏幕分为ldpi、mdpi、hdpi和xhdpi四类密度,并提供了资源适配策略,确保应用能在不同尺寸和密度的设备上良好运行。
摘要由CSDN通过智能技术生成

术语和概念


屏幕尺寸 


屏幕的物理尺寸,以屏幕的对角线长度作为依据(比如 Note2 5.5寸, S4 5.0寸)。
简而言之, Android把所有的屏幕尺寸简化为三大类:大,正常,和小。
程序可以针对这三种尺寸的屏幕提供三种不同的布局方案,然后系统会负责把你的布局方案以合适的方式渲染到对应的屏幕上,这个过程是不需要程序员用代码来干预的。

屏幕长宽比
屏幕的物理长度与物理宽度的比例。程序可以为制定长宽比的屏幕提供制定的素材,只需要用系统提供的资源分类符long和 notlong。

分辨率(重要)
屏幕上拥有的像素的总数。注意,虽然大部分情况下分辨率都被表示为“宽度×长度”,但分辨率并不意味着屏幕长宽比。在 Android系统中,程序一般并不直接处理分辨率,直接处理分辨率是用px,不直接就是用dip(dp)。

密度(重要)
以屏幕分辨率为基础,沿屏幕长宽方向排列的像素。
密度较低的屏幕,在长和宽方向都只有比较少的像素,而高密度的屏幕通常则会有很多 ——甚至会非常非常多——像素排列在同一区域。屏幕的密度是非常重要的,举个例子,长宽以像素为单位定义的界面元素(比如一个按钮),在低密度的屏幕上会 显得很大,但在高密度的屏幕上则会显得很小。

密度无关的像素( DIP )
指一个抽象意义上的像素,程序用它来定义界面元素。它作为一个与实际密度无关的单位,帮助程序员构建一个布局方案(界面元素的宽度,高度,位置)。
一个与密度无关的像素,在逻辑尺寸上,与一个位于像素密度为 160DPI的屏幕上的像素是一致的,这也是Android平台所假定的默认显示设备。在运行的时候,平台会以目标屏幕的密度作为基准,“透明地”处理所 有需要的DIP缩放操作。要把密度无关像素转换为屏幕像素,可以用这样一个简单的公式: pixels = dips * (density / 160)。举个例子,在 DPI为 240的屏幕上, 1个 DIP等于 1.5个物理像素。我们强烈推荐你用 DIP来定义你程序的界面布局,因为这样可以保证你的 UI在各种分辨率的屏幕上都可以正常显示。

为了简化程序员面在对各种分辨率时的困扰,也为了具备各种分辨率的平台都可以直接运行这些程序, Android平台将所有的屏幕以密度和分辨率为分类方式,各自分成了三类:
·三种主要的尺寸:大,正常,小;
·三种不同的密度:高( hdpi),中( mdpi)和低( ldp

Android 13(即 Android 3.2)中,DisplayMetrics的初始化流程与 Android 11(即 Android 4.0)类似,但具体实现方式有些细微差别。 1. WindowManagerService的构造函数中创建了DisplayManagerService对象: ``` mDisplayManager = new DisplayManagerService(context, wmHandler); ``` 2. DisplayManagerService的构造函数中先初始化了DisplayAdapter集合,然后通过DisplayManagerGlobal.getInstance()方法获取DisplayManagerGlobal对象: ``` mDisplayAdapters = new ArrayList<DisplayAdapter>(); mDisplayAdapters.add(new LocalDisplayAdapter(this)); mGlobal = DisplayManagerGlobal.getInstance(); ``` 3. DisplayManagerGlobal的构造函数中创建了DisplayManager对象,并调用DisplayManager对象的init()方法初始化DisplayMetrics: ``` mDm = new DisplayManagerService(context.getApplicationContext(), wmHandler); mDm.init(); ``` 4. DisplayManagerService的init()方法中先初始化了DisplayPowerController对象,然后遍历DisplayAdapter集合调用其init()方法,最后计算出DisplayMetrics: ``` mPowerController = new DisplayPowerController(context, this, mHandler, mBlanker, mDisplayReadyListener); for (DisplayAdapter adapter : mDisplayAdapters) { adapter.registerLocked(); adapter.initializeLocked(); } mDisplayInfos = mTempDisplayInfos.toArray(new DisplayDeviceInfo[mTempDisplayInfos.size()]); calculateInitialDisplayMetricsLocked(); ``` 其中,calculateInitialDisplayMetricsLocked()方法的实现如下: ``` private void calculateInitialDisplayMetricsLocked() { final int width = mDisplayInfos[0].mode.hResolution; final int height = mDisplayInfos[0].mode.vResolution; final float refreshRate = mDisplayInfos[0].mode.refreshRate; final float xdpi = width * 25.4f / mDisplayInfos[0].mode.physicalWidth; final float ydpi = height * 25.4f / mDisplayInfos[0].mode.physicalHeight; final float density = (xdpi + ydpi) / 2; final int densityDpi = (int) (density * 160 + 0.5f); mInitialDisplayWidth = width; mInitialDisplayHeight = height; DisplayMetrics metrics = new DisplayMetrics(); metrics.density = density; metrics.densityDpi = densityDpi; metrics.widthPixels = width; metrics.heightPixels = height; metrics.xdpi = xdpi; metrics.ydpi = ydpi; mInitialDisplayDensity = densityDpi; mCompatibleScreenWidthDp = (int) (width / (densityDpi / 160.0f)); mCompatibleScreenHeightDp = (int) (height / (densityDpi / 160.0f)); mDisplayMetrics.setTo(metrics); } ``` 可以看到,与 Android 11 中的实现非常类似,只是计算方法略有不同。在 Android 13 中,DisplayMetrics的xdpi是通过计算屏幕物理宽度和分辨率得出的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值