Android开发 屏幕适配之像素密度适配

Android开发 屏幕适配之像素密度适配由于市场上采用Android系统的设备种类繁多,迫使Andriod开发人员不得不做烦人的适配工作。适配工作包括对安装不同Android版本的设备进行适配,对不同屏幕的设备进行适配等。而屏幕适配又包括:屏幕尺寸(small,normal,large,xlarge,这些在Android3.2以上版本开始不建议使用,转而使用最小屏幕宽度如sw600dp,最小宽度,最小高度等)屏幕

大家好,又见面了,我是你们的朋友全栈君。

由于市场上采用Android系统的设备种类繁多,迫使Andriod开发人员不得不做烦人的适配工作。

适配工作包括对安装不同Android版本的设备进行适配,对不同屏幕的设备进行适配等。

而屏幕适配又包括:

屏幕尺寸(small,normal,large,xlarge , 这些在Android 3.2以上版本开始不建议使用,转而使用最小屏幕宽度如 sw600dp,最小宽度,最小高度等)

屏幕方向(port 竖屏,land 横屏)

屏幕像素密度(ldpi,mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi)

本文主要介绍屏幕像素密度适配相关知识。

考虑以下问题:

假如有一个设备屏幕像素密度为320dpi,在android工程res/drawable-hdpi目录放一张48×48大小的图片,布局文件中使用一个ImageView引用该图片,其中ImageView的宽高设置为跟随内容即wrap_content,那么屏幕显示的ImageView的宽高分别是多少像素?

答案:64px * 64px  

如果读者不知如何计算,则可参看下文。

先介绍一些概念。

屏幕像素密度指单位长度屏幕显示的像素,即常说的dpi (dots per inch),每英寸点数。密度越高显示画面就越清晰。

Android把像素密度按区间分成几种:

ldpi – low dpi, 低密度

mdpi – medium dpi 中密度

hdpi – high dpi 高密度

xhdpi – extra high dpi 超高密度

xxhdpi – extra extra high dpi 超超高密度

xxxhdpi – – extra extra extrahigh dpi 超超超高密度

不管设备像素密度是多少,都可以找到对应的分类。

当新建一个Android工程时,在res目录下可以看到drawable-xxx 目录,就是对应不同像素密度的资源。

那么这些目录又是如何使用呢?如何进行像素密度的适配?

首先,Android将mdpi即中密度作为基准线,即以密度160 dpi 作为参考值。

官方建议采用与屏幕像素密度无关的单位dp来描述button等控件的宽高,dp与px(像素单位)的关系为 px = dp * (dpi /160),也就是说如果设备像素密度为320dpi,则1dp = 2px ,对于宽度为160 dp的button,在160dpi的设备上占160px, 在320dpi的设备上占160*2=320px,这样在不同设备上看起来相对大小一样,就不会发生button“变小”的情况。

其次,不同像素密度,系统给定了其对应比例和倍数如下:

分类目录 ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi
密度(dpi) ~160 ~240 ~320  ~480 ~640
图片比例 1.5 2 3 4 6 8
倍数 0.75x 1x 1.5x 2x 3x 4x

根据上面表格,如果已知像素密度,则可知对应资源目录,系统会优先从该目录中寻找图片,如果找不到会从其他目录寻找。

因此对应不同密度设备,我们需要为其准备不同画质的图片,以便获得更好的效果。

在新建的Android工程中默认的机器人图标,在不同密度目录下大小不一样,其比例和表格上的比例一致,在我们准备资源图片时也要按该比例进行。

后面一行的“倍数”和比例相对应,关于它的作用后面会说明。

回到开头那个问题,如何找到答案。作者做了个测试。

测试机型:
Samsung N719  (像素密度: 320 dpi  屏幕宽高:720×1280)
Samsung I619  (像素密度: 160 dpi 屏幕宽高:320×480)

测试图片:取一张48×48大小图片(新建Android工程中mdpi目录下默认机器人图标),分别复制到drawable,drawable-mdpi,drawable-hdpi目录并使用不同文件名
xml布局控件:三个ImageView, 设置android:layout_width=”wrap_content”,android:layout_height=”wrap_content”,图片资源分别引用上述三个目录图片

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <LinearLayout 
        android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:layout_centerHorizontal="true"
	    android:layout_centerVertical="true"
	    android:orientation="vertical" >
	    
        <TextView 
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="fragment two"
	        android:background="@color/green" />
    
	    <ImageView 
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/default_test" />
	    
	    <ImageView 
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/mdpi_test" />
	    
	    <ImageView 
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/hdpi_test" />
    </LinearLayout>
    
</RelativeLayout>

测试结果:(测量三个ImageView宽度和高度,单位为px)
N719:
引用drawable,drawable-mdpi目录下图片的ImageView大小都为 96×96
引用drawable-hdpi目录下图片的ImageView大小为 64×64

I619:
引用drawable,drawable-mdpi目录下图片的ImageView大小都为 48×48
引用drawable-hdpi目录下图片的ImageView大小为 32×32

N719 测试截图:

Android开发 屏幕适配之像素密度适配

可以看到最后一个ImageView 跟其他两个比变小了。

由于我们设置ImageView宽高为wrap_content,那么其大小将跟图片大小一样,需要知道如何计算图片的宽高。

经过多次测试,可推出以下结论:

Android系统加载图片时设置图片宽高可能的处理流程为:(假设ImageView采用默认的scale type)
1.获取图片文件宽度width 

2.width的单位为dp,转换成px单位宽度 newWidth = width * (dpi/160)  

3.根据上述表格中mdpi,hdpi等的倍数,newWidth除以这个倍数得到最终图片宽度
其中除以倍数的过程也可能发生在步骤1,不过结果是一样的。

高度的计算方法类似。

对应上面的测试例子:

1.获取图片文件宽度48

2.转换成px单位宽度 newWidth = 48 * (320 / 160) = 96

3. 由于图片存放在hdpi目录,除以hdpi对应倍数1.5 ,得到图片宽度为 96/1.5 = 64

将I619设备测试结果验证,符合以上结论。后面尝试在ldpi中添加同样大小图片,测试ImageView宽度为 96/0.75 = 128,ImageView变大了,计算结果也与以上结论一致。

如何消除这种变大变小的现象呢?

将不同目录的图片大小换一下,比如hdpi下图片大小换成72×72,根据结论得出最后计算的图片宽度为 72 * (320/160) / 1.5 = 96 px ,这样ImageView看起来就不会变小了。

这里72×72就是系统默认hdpi下机器人图标大小,按照上述表格给的比例放置图片就不会有ImageView控件大小不一样的问题。

另外本测试可以看出,放在drawable目录的情况跟mdpi目录的情况一致,推测这两个对应的比例和倍数应该是一样的。

将ImageView的宽度高度设成固定大小比如48×48 dp,在N719上测试情况如下:

Android开发 屏幕适配之像素密度适配

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <LinearLayout 
        android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:layout_centerHorizontal="true"
	    android:layout_centerVertical="true"
	    android:orientation="vertical" >
	    
        <TextView 
	        android:layout_width="48dp"
	        android:layout_height="48dp"
	        android:text="fragment one"
	        android:background="@color/red" />
        
        <ImageView 
	        android:layout_width="48dp"
	        android:layout_height="48dp"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/ldpi_test" />
    
	    <ImageView 
	        android:layout_width="48dp"
	        android:layout_height="48dp"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/default_test" />
	    
	    <ImageView 
	        android:layout_width="48dp"
	        android:layout_height="48dp"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/mdpi_test" />
	    
	    <ImageView 
	        android:layout_width="48dp"
	        android:layout_height="48dp"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/hdpi_test" />
	    
	    <ImageView 
	        android:layout_width="48dp"
	        android:layout_height="48dp"
	        android:layout_marginTop="5dp"
	        android:layout_marginBottom="5dp"
	        android:background="@color/gray"
	        android:src="@drawable/hdpi_test_2" />
        
    </LinearLayout>
    
</RelativeLayout>

可以看出,ImageView固定大小后,如果不设置scale type,图片会按ImageView大小来显示,如果设置同样大小图片,ldpi 会压缩大小(128 -> 96),hdpi会拉伸大小(64 -> 96)

最后一个ImageView引用的图片@drawable/hdpi_test_2 其大小是72×72,可以看出它的画质最为清晰,这也正体现根据屏幕像素密度适配的重要性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/134310.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • MPP架构概念_体系架构是什么意思

    MPP架构概念_体系架构是什么意思MPP架构概念1.什么是MPPMPP(MassivelyParallelProcessing),即大规模并行处理。什么是并行处理?在数据库集群中,首先每个节点都有独立的磁盘存储系统和内存系统,其次业务数据根据数据库模型和应用特点划分到各个节点上,MPP是将任务并行的分散到多个服务器和节点上,在每个节点上计算完成后,将各自部分的结果汇总在一起得到最终的结果。什么是大规模?每台数据节点通过专用网络或者商业通用网络互相连接,彼此协同计算,作为整体提供数据库服务。整个集群称为非共享数据库集群,非

    2025年7月12日
    4
  • centos6.6关闭防火墙步骤「建议收藏」

    2019独角兽企业重金招聘Python工程师标准>>>…

    2022年4月16日
    61
  • 世纪互联云和华为共同打造的数据中心是一个很好的一步标志!

    世纪互联云和华为共同打造的数据中心是一个很好的一步标志!

    2022年1月2日
    165
  • 统信UOS命令大全 麒麟系统命令大全 Linux常用命令操作大全(非常全非常详细) ubuntu命令大全常用操作命令大全

    Linux常用命令大全(非常全!!!)最近都在和Linux打交道,感觉还不错。我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较短小但却功能强大。我将我了解到的命令列举一下,仅供大家参考:系统信息arch显示机器的处理器架构uname-m显示机器的处理器架构uname-r显示正在使用的内核版本dmidecode-q显示硬件系统部件-(SMBIOS/DMI)hdparm-i/dev/hd…

    2022年4月9日
    170
  • 基于IP地址划分VLAN

    基于IP地址划分VLAN实验环境:1、当检测IP在192.168.10.0./24时,PC接入交换机时,将其划分为VLAN10,且可以和VLAN10的服务器通信2、当检测IP在192.168.20.0/24时,PC接入交换机时,将其划分为VLAN20,且可以和VLAN20的服务器通信SW1<Huawei>system-view//进入全局配置模式[Huawei]undoinfo-centerenable//关闭信息告警提示[Huawei]sysnameSW1//

    2022年5月31日
    904
  • 从MVC框架看MVC架构的设计

    从MVC框架看MVC架构的设计尽管MVC早已不是什么新鲜话题了,但是从近些年一些优秀MVC框架的设计上,我们还是会发现MVC在架构设计上的一些新亮点。本文将对传统MVC架构中的一些弊病进行解读,了解一些优秀MVC框架是如何化解这些问题的,揭示其中所折射出的设计思想与设计理念。MVC回顾作为一种经典到不能再经典的架构模式,MVC的成功有其必然的道理,这个道理不同的人会有不同的解读,笔者最认同的一种观

    2022年4月7日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号