一.概念

几个概念:
1.像素:
像素是组成图像的最基本单位:点
该点自身有大小,其中保存了颜色值

2.屏幕尺寸:screen size
手机屏幕的物理尺寸。
单位:inch(英寸)
ex:4.0英寸 3.8英寸

3.分辨率:resolution
分辨率是指在长和宽的两个方向上各拥有的像素点
屏幕中物理像素点的总数.
单位:px (pixels)
ex: 480 x 800 , 1920 x 1080

4.屏幕像素密度:dots per inch.
每英寸中有多少个像素.
单位:dpi
ex:160dpi,表示1英寸中存在160个像素
dpi由屏幕尺寸和分辨率决定

5.密度:density
resolution  / screen size

6.密度无关像素:desity-independent pixel
与设备无关的像素,可以理解为是[逻辑像素]
>它用于在开发时,通过声明的方式(XML)定义UI元素之间的位置关系,当程序运行在
具体设备上之后,操作系统将会根据此dip值,换算像素,此像素值就是当前UI元素
在具体设备上的大小<
换算公式为:
pixel = dip * (dpi / 160);


二.布局单位

android布局文件中常见的几个单位:
px:像素
dip = dp:逻辑像素
sp:
(其他的pt,in,mm基本不用)

在android的xml布局文件中,Google建议控件的大小(width,height),外边距(margin),内边距(padding)使用dip(dp)定义
字号(textSize)使用sp定义

设计时通过Eclipse中的Graphical Layout可以看到控件之间的位置关系,此时的设计时界面是可以看到屏幕物理尺寸和分辨率的
在此尺寸和分辨率进行布局之后,到真机运行时,系统会根据真机的dpi,把设计时定义的控件的大小,边距从dip换算成实际的px

ex:
设计时我设置ImageView的width和height都为150dip,当程序运行在魅族MX2上时,获取ImageView的Width和Height看到其值为300px,
由于魅族MX2分辨率为:800 x 1280,即对应xhpdi,其屏幕密度为:320,
系统根据上文中的公式:pixel = dip * (dpi / 160) 进行换算: 300px = 150dip * (320dpi / 160);


三.目录

项目中的几个目录:
drawable-mdpi
drawable-hdpi
drawable-xhdpi
drawable-xxhdpi

drawable资源(更多时候是图片)被放在上述几个目录中,当程序启动时,系统会根据手机的硬件信息从合适的
drawable目录中加载资源,比如如果程序运行在魅族MX2上,那么就会从drawable-xhdpi中加载资源,如果运行在
Nexus One上,便从drawable-hdpi中加载资源

显然为了达到图片像素点与屏幕像素点一一对应,则需要多套图片资源,分别放在上述目录下,当时通常情况是
只会有一套资源,那只能放在一个目录下。

假设:
资源都放在drawable-mdpi中,当程序在魅族MX2运行时,由于手机dpi为320,则对应到drawable-xhdpi中加载资源,
但是由于此目录中没有资源,只能到其他目录中找,发现资源在drawable-mdpi中,便获取资源,载入程序中

由于在drawable-mdpi中的资源被认为其dpi为160,而当前真实dpi为320,那么要求在显示时候就需要每一英寸中的像素点从160个
增大到320个,所以系统对Bitmap进行了自动缩放,把图片放大了2倍.

那么这里就有一个疑问了。
假设,我们只有一套图片资源,是基于800 x 1280设计并且裁剪的,那么我们应该把它放在drawable-xhdpi目录下,没问题,
如果我把这些图片,放到drawable-mdpi下,那么就出现问题了,图片在绘制到屏幕上之后,必然会被放大,反之缩小了
所以,对应的图片资源,必须被放到适合的地方

如何禁止系统自动缩放图片资源?
如果我们不需要系统为我们自动缩放图片资源,可以把图片放到res/drawable-nodpi/目录下

getWidth和getHeight方法:

1.为什么同一张图片,在放入drawable-mdpi/drawable-hdpi/drawable-xhdpi/drawable-xxhdpi 目录中之后
创建Bitmap,getWidth()/getHeight(),不同目录下,结果不同

查看Bitmap源码发现,getWidth()方法是调用了nativeWidth(),至于nativeWidth()是调用SkBitmap类中的width()方法
SkBitmap与图片文件编码有关(头疼啊 - -)
那我就自作聪明的这么来理解SkBitmap的width()方法:

伪代码:
int width()
{
   //pixel = dip * (dpi / 160);
   // 获取设计时dpi
   // mdpi = 160
   // hdpi = 240
   // xhdpi = 320
   // xxhdpi = 480
   int desgin_dpi = get_desgin_dpi();
   // 获取设备相关真实dpi
   int system_dpi = get_system_dpi();

// 获取设计dpi与实际dpi的比例
   float rate = desgin_dpi / system_dpi * 1.0;
   // 获取图片实际像素数,即公式中的dip , 此值固定不便
   int img_file_width_piexls = get_img_width_pixels();

// 得到宽度,此值一致被Bitmap的getWidth()方法调用到
   return img_file_piexls * rate * (system_dpi / 160);
}

如果上述的假设是对的,那么说明,图片在不同目录时候,获取到的设计时dpi就不同,那么rate不同,
所以导致最终的结果不同.
(以上阐述未经过证明,纯属我yy)

2.上面也解释了为什么不同目录下获取到的数值不同,但是既然说getWidth()和getHeight获取到的是图片的宽高
图片是同一张图啊,一会640px,一会1280px,是图片的像素便了吗?

答:图片像素没变,宽高变了。getWidth和getHeight这个两个方法的返回值被用来描述Bitmap的宽和高,其单位为px,
在使用getWdith时,就不要用横向像素点个数来理解了,就简单的理解为是图片的宽。
getWidth为1280px时候,说明我们的图片被拉伸了,但是像素点个数没变,只是单个像素点的大小变大了,这样会
比较容易理解。(但是好像还是不知其所以然的样子,悲剧)

综上所述,清楚每一个目录的设计时对应分辨率和dpi是很重要的
基准dpi为160:
drawable-ldpi         -> 120dpi -> 0.75倍 -> 360  x 600
drawable-mdpi      -> 160dpi -> 1倍       -> 480  x 800
drawable-hdpi       -> 240dpi -> 1.5倍    -> 720  x 1200
drawable-xhdpi     -> 320dpi -> 2倍       -> 800  x 1280
drawable-xxhdpi   -> 480dpi -> 3倍       -> 1440 x 3840
drawable-xxxhdpi -> 640dpi -> 4倍       -> ...........


四.Examples

1.获取屏幕相关信息

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)
double diagonalPixels = Math.sqrt(Math.pow(width, 2)+Math.pow(height, 2)) ;
double screenSize = diagonalPixels/(160*density) ;

2.图片自动缩放后的宽高

Bitmap.getWidth()
Bitmap.getHeight()

3.获取图片真实尺寸(其像素值与在pc下查看到的一致)

// scaledWidth为图片在自动缩放资源目录中通过getWidth()获取到的数值
private int getImageRealWidth(int scaledWidth)
{
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int densityDpi = metric.densityDpi; return scaledWidth * 160 / densityDpi;
} // scaledHeight为图片在自动缩放资源目录中通过getHeight()获取到的数值
private int getImageRealHeight(int scaledHeight)
{
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int densityDpi = metric.densityDpi; return scaledHeight * 160 / densityDpi;
}

4.px –> dip , dip –> px

public static int dip2px(Context context, float dipValue)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(dipValue * scale + 0.5f);
} public static int px2dip(Context context, float pxValue)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(pxValue / scale + 0.5f);
}

[Android]图片资源管理学习的更多相关文章

  1. Android图片缓存之Lru算法

    前言: 上篇我们总结了Bitmap的处理,同时对比了各种处理的效率以及对内存占用大小.我们得知一个应用如果使用大量图片就会导致OOM(out of memory),那该如何处理才能近可能的降低oom发 ...

  2. Android图片处理

    相信做Android开发的小伙伴对于Android图片压缩.裁剪一定有很深的印象,今天我将带领大家一起学习一下这个看着高深莫测的知识,以便再以后的学习.工作中可以帮助到大家. 首先我们看一下这个问题出 ...

  3. Android图片缓存之Glide进阶

    前言: 前面学习了Glide的简单使用(Android图片缓存之初识Glide),今天来学习一下Glide稍微复杂一点的使用. 图片缓存相关博客地址: Android图片缓存之Bitmap详解 And ...

  4. Android图片缓存之初识Glide

    前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...

  5. Android图片缓存之Bitmap详解

    前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...

  6. android图片处理方法

    Java代码 //压缩图片大小 public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ...

  7. android图片处理方法(不断收集中)

    //压缩图片大小 public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArr ...

  8. Android 图片处理方法

    //压缩图片大小 public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArr ...

  9. Android图片异步加载之Android-Universal-Image-Loader

    将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...

随机推荐

  1. 【floyd】HDU 1874 畅通project续

    之后的题解偏重有用/总结性质,尽量理解算法本身而不是题,时间复杂度什么的也能够放放. 非常久之前做过这个题,当时使用dijkstra做的,关于几个最短路算法,分类的话能够分为下面几种. 1.单源最短路 ...

  2. 《Javascript权威指南》学习笔记之十二:数组、多维数组和符合数组(哈希映射)

    Array(数组)是JavaScript中较为复杂的数据类型,同Java.C#.VB等程序语言的数组相比.Javascript数组中的元素不必为同样的数据类型,能够在数组每一个元素上混合使用数字.日期 ...

  3. CodeForces Round #173 (282E) - Sausage Maximization 字典树

    练习赛的时候这道题死活超时....想到了高位确定后..低位不能对高位产生影响..并且高位要尽可能的为1..就是想不出比较好的方法了实现... 围观大神博客..http://www.cnblogs.co ...

  4. ubuntu 安装LaTex

    使用IDE来使用tex,如TexMaker. 1.到http://www.tug.org/texlive/acquire-netinstall.html 下载texlive. 2.linux下命令行, ...

  5. [置顶] oracle存储过程中单引号及字符串拼接处理

    在ORACLE中,单引号有两个作用,一是字符串是由单引号引用,二是转义.单引号的使用是就近配对,即就近原则.而在单引号充当转义角色时相对不好理解 1.从第二个单引号开始被视为转义符,如果第二个单引号后 ...

  6. bootstrap datatable项目封装支持单选多选

    自己在开发项目是根据自己的项目后台框架封装的jquery datatable插件基本上能集成到任何项目中使用,当然封装的还不够完美,给大家学习 调侃 使用介绍:query_dataTable({tab ...

  7. Oracle的序列

    Oracle的序列 序列介绍 序列是Oracle提供的用于产生一系列唯一数字的数据库对象. 使用序列能够实现自己主动产生主键值.序列也能够在很多用户并发环境中使用.为所实用户生成不反复的顺序数字,并且 ...

  8. HDU 2045 不easy系列之(3)—— LELE的RPG难题

    思路: 1.若前n-1位涂的颜色是符合条件的,则因为首尾不同,再加入一位时,仅仅有1种方法:即s[n] = s[n-1] 2.若前n-1位组成的串不符合,再加入一位后合法.即由于首尾同样而引起的不合法 ...

  9. linux下编译qt5.6.0静态库——configure配置(超详细,有每一个模块的说明)(乌合之众)

    linux下编译qt5.6.0静态库 linux下编译qt5.6.0静态库 configure生成makefile 安装选项 Configure选项 第三方库: 附加选项: QNX/Blackberr ...

  10. Delphi + Asm - TBits类的学习

    技术交流,DH讲解. 在D2010的classes中有个TBits类,这个类主要是位操作的. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 TBits = class privat ...