Android如何支持不同的像素密度

支持不同的像素密度

Android设备不仅有不同的屏幕尺寸(手机,平板电脑,电视等),而且它们的屏幕也有不同的像素大小。 也就是说,虽然一个设备每平方英寸有160个像素,但另一个设备在同一空间中可以容纳480个像素。 如果不考虑像素密度的这些变化,系统可能会缩放图像(导致图像模糊),或者图像可能会以完全错误的尺寸显示。

使用与密度无关的像素

第一个必须避免的陷阱便是使用像素来定义距离或大小。 用像素定义尺寸是一个问题,因为不同的屏幕具有不同的像素密度,因此相同数量的像素可以对应于不同设备上的不同物理尺寸。
在这里插入图片描述
图1.两个尺寸相同但像素密度不同的设备

要在具有不同密度的屏幕上保留UI的可见大小,必须使用与密度无关的像素(dp)作为度量单位来设计UI。 1dp是一个虚拟像素单元,大致等于中密度屏幕上的一个像素(160dpi;“基线”密度)。 Android会将此值转换为相应密度的相应实际像素数。

例如,考虑图1中的两个设备。如果要将视图定义为“100px”宽,则左侧设备上的视图会显得更大。 因此,您必须使用“100dp”来确保它在两个屏幕上显示相同的大小。

但是,在定义文本大小时,应使用可缩放像素(sp)作为单位(但不要将sp用于布局大小)。 默认情况下,sp单位与dp的大小相同,但它会根据用户的首选文本大小调整大小。

例如,当指定两个视图之间的间距时,使用dp:


<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/clickme"
    android:layout_marginTop="20dp" />

指定文本大小时,使用sp:

<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp" />

在某些情况下,您需要在dp中表示尺寸,然后将它们转换为像素。 将dp单位转换为屏幕像素很简单:

Px = dp *(dpi / 160)

试想一下,在用户的手指在可识别滚动或拖动手势的应用程序中移动了至少16个像素后,。 在基线(160dpi)屏幕上,用户必须移动 16px/160 dpi,大约等于1/10英寸(或2.5 mm)。 在具有高密度显示器(240dpi)的设备上,用户必须移动 16px/240 dpi,大约等于1/15英寸(或1.7 mm)。 距离较短,因此应用程序对用户更敏感。

提供备用位图

要在具有不同像素密度的设备上提供良好的图形质量,您应该在应用程序中为每个密度桶提供多个版本的每个位图,并以相应的分辨率。否则,Android必须缩放位图,使其在每个屏幕上占据相同的可见空间,从而导致缩放伪像,例如模糊。

在这里插入图片描述

图2.不同密度大小的位图的相对大小

在应用中使用多个资源密度文件夹。

表1描述了可用的不同配置限定符以及它们适用的屏幕类型。

表1.不同像素密度的配置限定符。

密度限定符说明
ldpi用于低密度(ldpi)屏幕的资源(~120dpi)。
mdpi用于中密度(mdpi)屏幕的资源(~160dpi)。
hdpi用于高密度(hdpi)屏幕的资源(~240dpi)。
xhdpi用于超高密度(xhdpi)屏幕的资源(~320dpi)。
xxhdpi用于额外高密度(xxhdpi)屏幕的资源(~480dpi)。
xxxhdpi用于额外超高密度(xxxhdpi)屏幕的资源(~640dpi)。
nodpi用于与密度无关的资源。 无论当前屏幕的密度如何,系统都不会缩放使用此限定符标记的资源。
tvdpi主要用于电视,大多数应用程序不需要它 - 提供mdpi和hdpi资源就足以满足大多数应用程序的要求,系统会根据需要进行扩展。 如果您发现有必要提供tvdpi资源,则应将其大小设置为1.33 * mdpi。 例如,mdpi屏幕的100px x 100px图像对于tvdpi应为133px x 133px。

要为不同的密度创建可替换drawable位图,应遵循六个主要密度之间的3:4:6:8:12:16缩放比例。 例如,如果您有一个drawable位图的中等密度屏幕为48x48像素,则所有不同的大小应为:

36x36(0.75x)用于低密度(ldpi)
48x48(1.0x基线)用于中密度(mdpi)
72x72(1.5x)用于高密度(hdpi)
96x96(2.0x)超高密度(xhdpi)
144x144(3.0x)额外高密度(xxhdpi)
192x192(4.0x)额外超高密度(xxxhdpi)
然后,将生成的图像文件放在res /下的相应子目录中,系统将根据运行应用程序的设备的像素密度自动选择正确的文件:

res/
  drawable-xxxhdpi/
    awesome-image.png
  drawable-xxhdpi/
    awesome-image.png
  drawable-xhdpi/
    awesome-image.png
  drawable-hdpi/
    awesome-image.png
  drawable-mdpi/
    awesome-image.png

之后只要你引用@drawable/awesomeimage,系统就会根据屏幕的dpi选择合适的位图。 如果没有为该密度提供密度特定的资源,系统会选择下一个最佳匹配并对其进行缩放以适合屏幕。

使用矢量图形

创建图像的多个密度特定版本的替代方法是仅创建一个矢量图形。 矢量图形使用XML创建图像以定义路径和颜色,而不是使用像素位图。 因此,矢量图形可以缩放到任何尺寸而不会缩放工件,尽管它们通常最适合图标等插图,而不是照片。

矢量图形通常作为SVG(可缩放矢量图形)文件提供,但Android不支持此格式,因此您必须将SVG文件转换为Android的矢量drawable格式。

使用Android Studio 中的Vector Asset 工具可以轻松地将SVG转换为矢量图drawable文件,如下所示:
在这里插入图片描述
图3.使用Android Studio导入SVG

您可能会注意到Asset Studio窗口中出现了一些错误,指出了矢量drawable不支持的文件的某些属性。 但这不会阻止您导入 - 只是忽略不受支持的属性。

点击下一步。

在下一个屏幕上,确认源集中项目中文件的位置,然后单击“完成”。

因为可以在所有像素密度上使用一个矢量drawable,所以此文件位于默认的drawables目录中(不需要使用特定于密度的目录):

res/
  drawable/
    ic_android_launcher.xml

适配不常见的密度建议

为了更好地理解在运行时操作图形时如何支持多个密度,您应该了解系统有助于通过以下方式确保适当的位图比例:

可缩放的资源(例如位图drawables)

根据当前屏幕的密度,系统使用您应用中的任何密度特定资源。如果资源不具有正确的密度,系统将加载默认资源并根据需要向上或向下扩展。系统假定默认资源(来自没有配置限定符的目录中的资源)是针对基线像素密度(mdpi)设计的,并将这些位图的大小调整为适合当前像素密度的大小。

如果请求预先缩放资源的尺寸,系统将返回表示缩放后尺寸的值。例如,mdpi屏幕上设置为50x50像素的位图在hdpi屏幕上缩放到75x75像素(如果没有替代hdpi资源),系统会报告大小。

在某些情况下,您可能不希望Android预先扩展资源。避免预缩放的最简单方法是将资源放在具有nodpi配置限定符的资源目录中。例如:
res /drawable-nodpi /icon.png

当系统使用此文件夹中的icon.png位图时,它不会根据当前设备密度对其进行缩放。

自动缩放像素尺寸和坐标

可以通过将清单中的android:anyDensity设置为“false”或通过将inScaled设置为“false”以编程方式为Bitmap禁用预缩放尺寸和图像。在这种情况下,系统会在绘制时自动缩放任何绝对像素坐标和像素尺寸值。这样做是为了确保像素定义的屏幕元素仍然以与基线像素密度(mdpi)大致相同的物理尺寸显示。系统会对应用程序透明地处理此缩放,并将缩放的像素尺寸报告给应用程序,而不是物理像素尺寸。

文章地址:https://blog.youkuaiyun.com/u013560890/article/details/89679784

原文地址:https://developer.android.com/training/multiscreen/screendensities.html#TaskUseDP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值