手机屏幕对角线的物理尺寸。单位英寸(inch),一英寸大约 2.54cm。常见的手机屏幕尺寸有 4.7 英寸、5.0英寸、5.5 英寸、6.0 英寸等。android
像素(英语:Picture Element),Pixel 的缩写。液晶屏显示图像,放大来看是一个个小点组成的,这些小点就是像素点。git
分辨率(英语:Image resolution),又称解析度、解像度,能够从显示分辨率与图像分辨率两个方向来分类。github
在 Android 设备中指的是显示分辨率,即屏幕分辨率。也就是屏幕所能显示的像素有多少,好比:手机分辨率 1920 x 1080。算法
在图片中指是图像分辨率,则是单位英寸中所包含的像素点数。好比:图片分辨率 600 x 400。json
每英寸点数(英语:Dots Per Inch,缩写:DPI)是一个量度单位,用于点阵数码影像,指每一英寸长度中,取样、可显示或输出点的数目。服务器
通常用于打印机、鼠标等设备分辨率的度量单位。网络
好比:打印机输出可达 600 DPI 的分辨率,表示打印机能够在每一平方英寸的面积中能够输出 600 x 600 = 360000 个输出点。app
鼠标的 DPI 参数,指的是鼠标在桌面上移动一英寸的距离的同时,鼠标光标可以在屏幕上移动多少「点」。ide
每英寸像素(英语:Pixels Per Inch,缩写:PPI),又被称为像素密度。布局
通常用来计量计算机显示器,电视机和手持电子设备屏幕的精细程度。一般状况下,每英寸像素值越高,屏幕能显示的图像也越精细。
当咱们把相同分辨率的图片,放在具备相同像素显示的屏幕上显示时。每个像素,屏幕上对应一个点显示,此时 DPI = PPI。 好比:咱们把分辨率为 m x n
的图片,放在最大支持 m x n
像素的屏幕上时,DPI = PPI。
可是,实际上,咱们所须要显示图片的分辨率,跟屏幕参数匹配的几率仍是很小的。咱们来分析下,不匹配时的状况:
当咱们把 1280 x 720
的图片,放在 800 x 480
的 4 英寸的屏幕与 1920 x 1080
的 5.5 英寸的屏幕上显示时的结果为:
PPI 是屏幕的显示性能,因此与显示的图片没有关系,是固定的值,可是 DPI 与显示的图片是有关系的。
1280 x 720
的图片放在 800 x 480
的 4 英寸的屏幕上显示虽然图片一行有 720 个像素,可是屏幕一行最多只能显示 480 个点,因此 DPI = PPI = 233
,已经达到屏幕的最大显示能力。
1280 x 720
的图片放在 1920 x 1080
的 5.5 英寸的屏幕上显示虽然屏幕一行有 1080 个点,可是图片一行最多只能显示 720 个像素,因此 DPI = 267 < PPI
,并未达到屏幕的最大显示能力,未达到屏幕的最佳显示效果。
经过上面分析能够获得:
一句话总结下就是 DPI 表示印刷品点的密度,PPI 表示显示设备点的密度。
因为显示器的 DPI 是固定的,不像打印机那样能够调整,因此针对显示器的设计时 DPI = PPI。
计算显示器的每英寸像素值,须要肯定屏幕的尺寸和分辨率。
其中:
根据屏幕每英寸像素值的不一样,Android 中将平板电脑和手机的屏幕分为下面几类:
密度名称 | 每英寸像素值 | 图标尺寸 |
---|---|---|
低密度(LDPI) | ~120dpi | 36 x 36 px |
中密度(MDPI) | 120dpi ~ 160dpi | 48 x 48 px |
高密度(HDPI) | 160dpi ~ 240dpi | 72 x 72 px |
超高密度(XHDPI) | 240dpi ~ 320dpi | 96 x 96 px |
超超高密度(XXHDPI) | 320dpi ~ 480dpi | 144 x 144 px |
超超超高密度(XXXHDPI) | 480dpi ~ 640dpi | 192 x 192 px |
DP 或者 DIP,是 Android 开发用的单位。1dp 表示在屏幕点密度为 160ppi 时 1px 长度。
因为 Android 设备屏幕众多,不可能为每一个屏幕单独开发,因此用下面公式计算在不一样屏幕上的像素数。
同一图标在分辨率不一样的设备上显示时,会出现以下效果:
能够看到上图第 1 和第 2 个设备两个屏幕尺寸相同,因为它们分辨率的不一样,同一个图标在两个设备上显示的尺寸相差很大。
那么,图片显示大小是由什么决定的呢,屏幕尺寸吗?上图第 1 和第 2 个设备屏幕都是 4.3 英寸。
仍是由于分辨率呢?上图第 2 和第 3 个设备屏幕都是 720 x 1280 的分辨率。
最后咱们找到了像素密度(density),也就是像素数和屏幕尺寸的比值。density 是每单位长度容纳的像素数量,通常用像素/英寸,也就是 Pixel per inch(PPI)。
对比上图能够知道,PPI 越低图片显示的越大,PPI 越高图片显示的越小。
要让不一样屏幕显示图片的大小相同,就须要对图片进行缩放,给高 PPI 屏提供更大的图片。
高 PPI 屏幕须要更大的图片才能获得一样的显示效果,反之亦然。
PPI 和图片 px 的关系,以下:
选定一个 PPI 值做为基础绘制图片,用 PPI 的比值计算出图片缩放比例,就能够适配各类屏幕。
Android 选定的这个基础值就是 160ppi
。
咱们已经解决了图片放大缩小的问题,还须要一个单位用来描述长度。
由于 px 不固定,inch 不方便,因此 Android 创造了一个新的单位 dp,中文名密度无关像素。而且规定在 160ppi 的屏幕上 1dp = 1px。
设计师只须要针对 160ppi 的显示屏设计并制图,安卓会根据当前手机屏幕的 PPI 值来放大缩小图片,在不一样的屏幕上获得相近的显示效果。
Android 设备的文字单位是 SP,简单理解和 DP 是相同的。另外 SP 会随着系统的字体大小改变,而 DP 则不会。
Google 推荐咱们使用 12sp 以上的大小,一般可使用 12sp、14sp、18sp、22sp。最好不要使用「奇数」和「小数」。
设置视图的宽高为 wrap_content 时,视图大小会根据内容自动增长。
设置视图宽高位 match_parent 时,视图大小始终与父级同样大。
LinerLayout 是一个视图组,用于使全部子视图在单个方向(垂直或水平)保持对齐。 可使用 android:orientation
属性指定布局方向。
使用线性布局时,将某一个或者多个子视图的宽或者高设置为 0dp
,设置 weight 值为 1
。
weight 值为 1 的子视图将会充满父视图剩余的空间,若是设置多个子视图的 weight 都为 1,那么这些子视图将平分并充满父视图剩余的空间。
RelativeLayout 是一个视图组,显示相对位置的子视图。使用 RelativeLayout 能够将子视图定位在任意位置。
使用方式以下:
|- layout // 无限定符,默认布局
|- main.xml
|- layout-small // 小屏幕设备
|- main.xml
|- layout-normal // 中等屏幕设备
|- main.xml
|- layout-large // 大屏幕设备
|- main.xml
|- layout-xlarge // 超大屏幕设备
|- main.xml
复制代码
最小宽度限定符就是设置设备屏幕大于或等于最小宽度时加载的视图。
例如,7 英寸平板电脑最小宽度为 600dp,若是但愿的 UI 在这些屏幕上显示两列,但在较小屏幕上显示单列,就可使用最小宽度限定符。
|- layout // 无限定符,默认布局显示单列
|- main.xml
|- layout-sw600dp // 设备宽度为 600dp 以上时显示两列
|- main.xml
复制代码
若是适配的屏幕设备比较多,为了方便视图文件的管理,咱们可使用布局别名。
|- layout
|- main.xml // 单列布局
|- main_twopanes.xml // 双列布局
|- values-large
|- layout.xml
|- values-sw600dp
|- layout.xml
复制代码
res/values-large/layout.xml
:<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
复制代码
res/values-sw600p/layout.xml
:<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
复制代码
后两个文件内容彻底相同,但它们实际上并未定义布局, 而只是将 main
设置为 main_twopanes
的别名。因为这些文件具备 large
和 sw600dp
选择器,所以它们适用于任何 Android 版本的平板电脑和电视(低于 3.2 版本的平板电脑和电视匹配 large
,高于 3.2 版本者将匹配 sw600dp
)。
|- layout
|- main.xml // 单列布局
|- main_twopanes.xml // 双列布局
|- values-large-land // 大屏幕横向
|- layout.xml
|- values-sw600dp-port // 最小宽度 600dp 横向
|- layout.xml
复制代码
官方建议的图标尺寸:
密度名称 | 每英寸像素值 | 图标尺寸 | 图片资源目录 |
---|---|---|---|
LDPI | ~120dpi | 36 x 36 px | mipmap-ldpi |
MDPI(基准) | 120dpi ~ 160dpi | 48 x 48 px | mipmap 或 mipmap-mdpi |
HDPI(1.5倍) | 160dpi ~ 240dpi | 72 x 72 px | mipmap-hdpi |
XHDPI(2倍) | 240dpi ~ 320dpi | 96 x 96 px | mipmap-xhdpi |
XXHDPI(3倍) | 320dpi ~ 480dpi | 144 x 144 px | mipmap-xxhdpi |
XXXHDPI(4倍) | 480dpi ~ 640dpi | 192 x 192 px | mipmap-xxxhdpi |
按照官方密度类型进行切图便可,通常状况下只须要根据主流设备选择所须要的资源文件便可。
目前已知主流设备屏幕:
屏幕分辨率 | 屏幕尺寸 | PPI | 对应密度 | 图片资源文件夹 |
---|---|---|---|---|
240 x 320 | 2.5 | 160 | MDPI(基准) | drawable-mdpi |
400 x 800 | 4.0 | 224 | HDPI(1.5倍) | drawable-hdpi |
720 x 1280 | 4.7 | 313 | XHDPI(2倍) | drawable-xhdpi |
1080 x 1920 | 5.5 | 401 | XXHDPI(3倍) | drawable-xxhdpi |
1440 x 2560 | 6.0 | 490 | XXXHDPI(4倍) | drawable-xxxhdpi |
红色框区域:表示纵向拉伸的区域,当图片须要纵向拉伸的时候它会只指定拉伸红色区域,其余区域在纵向是不会拉伸。
绿色框区域:表示横向拉伸的区域,当图片须要横向拉伸的时候它会只指定拉伸绿色区域,其余区域在横向是不会拉伸的。
显然红色和绿色相交的部分是既会进行横向拉伸也会进行纵向拉伸。
黄色区域:表示前景能显示的横向范围。即前景的最左边能够显示到什么地方,最右边能够显示的什么地方。
蓝色区域:表示前景能显示的纵向范围。即前景的最上面能够显示到什么地方,最下面能够显示的什么地方。
蓝色和黄色相交部分:表示整个前景能显示的区域。一个区域是矩形的,蓝色规定了上下边界,黄色规定了左右边界,二者共同固然也就规定了一个矩形区域。
矢量图是根据几何特性来绘制图形,矢量能够是一个点或一条线,矢量图只能靠软件生成,文件占用内在空间较小,由于这种类型的图像文件包含独立的分离图像,能够自由无限制的从新组合。
它的特色是放大后图像不会失真,和分辨率无关,适用于图形设计、文字设计和一些标志设计、版式设计等。
SVG 指可伸缩矢量图形 (Scalable Vector Graphics)。用来定义用于网络的基于矢量的图形,SVG 使用 XML 格式定义图形,图像在放大或改变尺寸的状况下其图形质量不会有所损失。
Android 中对矢量图的支持就是对 SVG 的支持。使用方式比较简单,这里再也不赘述。
ImageView 是 Android 中最经常使用的控件之一,而在使用 ImageView 时,必不可少的会使用到它的 scaleType 属性。该属性指定了你想让 ImageView 如何显示图片,包括是否进行缩放、等比缩放、缩放后展现位置等。
Android 提供了八种 scaleType的 属性值,每种都对应了一种展现方式。
本地加载图片时,根据设备屏幕分辨率或像素密度,向服务器请求对应级别的图片资源。
Android P 提供提供的刘海屏适配方案,详见:Android 开发文档 - 支持显示切口
刘海屏适配思路:
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
可将刘海区域变成一条黑色边)。若是全屏显示,获取到危险区域(刘海区域),让操做区域避开危险区域便可。Google 建议咱们支持更多的设备,可是根据需求可能须要不支持某些设备。好比,仅支持手机不支持平板电脑。咱们就能够增长不支持的屏幕设备。
若是应用仅支持小屏幕尺寸和标准屏幕尺寸,能够这么作:
<manifest ... >
<compatible-screens>
<!-- 全部的小尺寸屏幕 -->
<screen android:screenSize="small" android:screenDensity="ldpi" />
<screen android:screenSize="small" android:screenDensity="mdpi" />
<screen android:screenSize="small" android:screenDensity="hdpi" />
<screen android:screenSize="small" android:screenDensity="xhdpi" />
<!-- 全部的标准尺寸屏幕 -->
<screen android:screenSize="normal" android:screenDensity="ldpi" />
<screen android:screenSize="normal" android:screenDensity="mdpi" />
<screen android:screenSize="normal" android:screenDensity="hdpi" />
<screen android:screenSize="normal" android:screenDensity="xhdpi" />
</compatible-screens>
...
<application ... >
...
<application>
</manifest>
复制代码
若是应用仅支持平板电脑或电视,能够这么作:
<manifest ... >
<supports-screens android:smallScreens="false" android:normalScreens="false" android:largeScreens="true" android:xlargeScreens="true"/>
...
</manifest>
复制代码
2018 年 5 月,字节跳动技术团队提出了一种低成本的屏幕适配方式,强烈推荐你们看一下:一种极低成本的 Android 屏幕适配方式
欢迎关注个人公众号,分享各类技术干货,各类学习资料,职业发展和行业动态。
欢迎加入技术交流群,来一块儿交流学习。