android开发图片分辨率问题解决方案

移动开发 Android
一直受到android开发图片分辨率问题困扰.drawable-(xdpi,hdpi,mdpi,ldpi,nodpi)这几个文件夹到底怎么放图片呢?

dpi是什么呢?

dpi是“dot per inch”的缩写,每英寸像素数。
四种密度分类: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)
一般情况下的普通屏幕:ldpi是120,mdpi是160,hdpi是240,xhdpi是320。

dpi计算公式
DPI=对角线的像素值/尺寸

手机屏幕分辨率和屏幕密度是两码事!并不是800*480的分辨率手机图片就应该放在hdpi文件夹中。5.0英寸 800*480属于mdpi

也可以通过代码获取:

DisplayMetrics metric = new DisplayMetrics(); 
       getWindowManager().getDefaultDisplay().getMetrics(metric); 
       int width = metric.widthPixels;  // 屏幕宽度(像素) 
       int height = metric.heightPixels;  // 屏幕高度(像素) 
       float density = metric.density;  // 屏幕密度(0.75 / 1.0 / 1.5) 
       int densityDpi = metric.densityDpi;  // 屏幕密度DPI(120 / 160 / 240) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

android会根据屏幕本身的尺寸与密度特性,自动载入对应的资源,并把它们从逻辑像素(DIP,用于定义界面布局)转换成屏幕上的物理像素。

首先看看 系统是如何通过Resources的getDrawable(int id)方法找图片的

public Drawable getDrawable(int id) throws NotFoundException { 
        TypedValue value; 
        synchronized (mAccessLock) { 
            value = mTmpValue; 
            if (value == null) { 
                value = new TypedValue(); 
            } else { 
                mTmpValue = null
            } 
            getValue(id, value, true); 
        } 
        Drawable res = loadDrawable(value, id); 
        synchronized (mAccessLock) { 
            if (mTmpValue == null) { 
                mTmpValue = value; 
            } 
        } 
        return res; 
    } 
  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

TypedValue 我们可以理解为存储数据的类型,主要被Resouces使用于持有的资源值
通过getValue(id,value,true)方法去得到该id的资源的属性

public void getValue(int id, TypedValue outValue, boolean resolveRefs) 
            throws NotFoundException { 
        boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs); 
        if (found) { 
            return
        } 
        throw new NotFoundException("Resource ID #0x" 
                                    + Integer.toHexString(id)); 
    } 
  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

最后通过loadDrawable(value, id)得到drawable,该方法到了底层的C代码,大致意思就是通过TypedValue中的方法和属性就可以获得我们想要的属性值,然后加载图片

OK,下面来做个实验.

试验一: 手机是1280*720 4.3英寸 属于xdpi 图片分辨率为960*640 (按正常图片不缩放 图片放在手机里面 应该不会充满 整个手机) 我把图片放在不

文件夹 加载时间(ms) 图片显示 说明

drawable 311 充满屏幕 图片有拉伸

drawable-nodpi 130 未充满屏幕 图片显示正常

drawable-ldpi 442 充满屏幕 图片有拉伸

drawable-mdpi 383 充满屏幕 图片有拉伸

drawable-hdpi 226 充满屏幕 图片有拉伸

drawable-xhdpi 109 未充满屏幕 图片显示正常

试验二: 手机是800*480 4.3英寸 属于hdpi 图片分辨率为960*640 (按正常图片不缩放 图片放在手机里面 应该充满 整个手机) 我把图片放在不同drawable文件夹中

文件夹 加载时间(ms) 图片显示 说明

drawable 290 充满屏幕 图片拉伸

drawable-nodpi 127 充满屏幕 图片显示正常

drawable-ldpi 369 充满屏幕 图片拉伸

drawable-mdpi 346 充满屏幕 图片拉伸

drawable-hdpi 124 充满屏幕 图片显示正常

drawable-xhdpi 241 未充满屏幕 图片缩放

得到结论:

drawable-nodpi 中 图片不会被拉伸

系统在得到图片时候,会先到设备对应的dpi的文件夹下去去找资源文件,找到后应该不会做缩放直接返回图片。

如果没有在对应的dpi文件夹中找到,回去其他文件夹中查找,找到后会做相应的缩放。

在高dpi找到的图片会缩放,在低dpi的会拉伸

还有就是 源码中可以看出 loadDrawable的过程实在C层做的。通过系统资源id加载会比java层直接加载图片更便捷。

责任编辑:张叶青 来源: eoe Android开发者社区
相关推荐

2012-05-09 10:08:41

跨机房

2010-08-04 10:20:30

Flex组件开发

2010-09-27 13:14:42

JVM内存限制

2010-03-30 16:04:34

Linux Nginx

2021-12-21 22:57:04

Windows 11Windows微软

2010-04-28 19:24:17

Hp unix

2011-03-23 16:38:28

LAMP

2010-10-08 13:09:38

JavaScript数

2010-02-06 14:54:11

C++指针漂移

2010-05-31 12:53:56

Nagios apac

2010-08-30 12:46:42

DIV+CSS

2009-09-03 16:09:48

.net回车符

2010-08-26 12:59:29

marginCSS

2010-02-23 17:49:56

WCF传输大数据

2010-09-15 14:14:29

IE6position

2019-04-04 13:11:37

React内存泄露memory leak

2010-02-24 10:55:01

WCF跨域访问

2010-07-30 12:40:00

Flex跨域访问

2010-08-26 08:45:32

margin:0pxa

2010-05-04 11:30:29

Oracle汉字长度
点赞
收藏

51CTO技术栈公众号