一、基本概念

参考
关于Android设备屏幕大小及密度的系统参数类
Android中px dpi dip density densityDpi 的相关说明
dpi 、 dip 、分辨率、屏幕尺寸、px、density 关系以及换算(终结版)

Px(Pixel像素)
不同设备显示效果相同。这里的“相同”是指像素数不会变,比如指定UI长度是100px,那不管分辨率是多少UI长度都是100px。也正是因为如此才造成了UI在小分辨率设备上被放大而失真,在大分辨率上被缩小。

Screen Size(屏幕尺寸)
一般所说的手机屏幕大小如1.6英寸、1.9英寸、2.2英寸,都是指的对角线的长度,而不是手机面积。我们可以根据勾股定理获取手机的宽和长,当然还有面积。

Resolution(分辨率)
指手机屏幕垂直和水平方向上的像素个数。比如分辨率是480*320,则指设备垂直方向有480个像素点,水平方向有320个像素点。

Dpi(dots per inch像素密度)
dpi是密度,即屏幕每英寸所包含的像素数。比如一个手机屏幕宽2英寸长3英寸,分辨率320480,则密度是160dpi.*
float xdpi = getResources().getDisplayMetrics().xdpi;//获取屏幕密度值
安卓规定,在160dpi屏幕上,1dp等于1px.这样在160dpi屏幕上指定的1dp宽度按钮,到了320dpi屏幕,宽度自动变成2px,保持了所占屏幕比例。
注意:该值对应于DisplayMetrics类中属性densityDpi的值。

Density(密度)
density其实是没单位的,他就是一个比例值,也可以叫缩放系数,值为 densityDpi/160。常见取值 1.5 , 1.0 。
dpi的单位是 像素/英寸,比较符合物理上面的密度定义,密度不都是单位度量的值么,所以我更喜欢把dpi叫像素密度,简称密度,density还是就叫density。
注意:该值对应于DisplayMetrics类中属性density的值。

density densityDpi
1 160
1.5 240
2 320
3 480
3.5 560
4 640

Dip(Device-independent pixel,设备独立像素)
同dp,可作长度单位,不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。dip和具体像素值的对应公式是dip值 =设备密度/160* pixel值,可以看出在dpi(像素密度)为160dpi的设备上1px=1dip

Sp(ScaledPixels放大像素)
主要用于字体显示(best for textsize)。根据 google 的建议,TextView 的字号最好使用 sp 做单位,而且查看TextView的源码可知 Android 默认使用 sp 作为字号单位。
类似px,传统的pt是磅数,1磅等于1/72英寸,pt一般作为字体单位来使用。


/**

  • 系统参数类
  • @author wader

*/
public class MySystemParams {
private final String TAG = "SystemParams";
private static MySystemParams params;
public int screenWidth;// 屏幕宽度,单位为px
public int screenHeight;// 屏幕高度,单位为px
public int densityDpi;// 屏幕密度,单位为dpi
public float scale;// 缩放系数,值为 densityDpi/160
public float fontScale;// 文字缩放系数,同scale

public final static int SCREEN_ORIENTATION_VERTICAL = 1; // 屏幕状态:横屏
public final static int SCREEN_ORIENTATION_HORIZONTAL = 2; // 屏幕状态:竖屏
public int screenOrientation = SCREEN_ORIENTATION_VERTICAL;// 当前屏幕状态,默认为竖屏

/**

  • 私有构造方法
  • @param activity
    */
    private MySystemParams(Activity activity) {
    DisplayMetrics dm = new DisplayMetrics();
    activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
    screenWidth = dm.widthPixels;
    screenHeight = dm.heightPixels;
    densityDpi = dm.densityDpi;
    scale = dm.density;
    fontScale = dm.scaledDensity;

screenOrientation = screenHeight > screenWidth ? SCREEN_ORIENTATION_VERTICAL
: SCREEN_ORIENTATION_HORIZONTAL;
}

/**

  • 获取实例
  • @param activity
  • @return
    */
    public static MySystemParams getInstance(Activity activity) {
    if (params == null) {
    params = new MySystemParams(activity);
    }
    return params;
    }

/**

  • 获取一个新实例
  • @param activity
  • @return
    */
    public static MySystemParams getNewInstance(Activity activity) {
    if (params != null) {
    params = null;
    }
    return getInstance(activity);
    }

/**

  • 参数信息
    */
    public String toString() {

return TAG
+ ":[screenWidth: "
+ screenWidth
+ " screenHeight: "
+ screenHeight
+ " scale: "
+ scale
+ " fontScale: "
+ fontScale
+ " densityDpi: "
+ densityDpi
+ " screenOrientation: "
+ (screenOrientation == SCREEN_ORIENTATION_VERTICAL ? "vertical"
: "horizontal") + "]";
}
}

二、屏幕适配

参考
android 屏幕适配
Android屏幕适配全攻略(最权威的官方适配指导)
我们新建一个Android项目后应该可以看到很多drawable文件夹,分别对应不同的dpi

  • drawable-ldpi (dpi=120, density=0.75)
  • drawable-mdpi (dpi=160, density=1)
  • drawable-hdpi (dpi=240, density=1.5)
  • drawable-xhdpi (dpi=320, density=2)
  • drawable-xxhdpi (dpi=480, density=3)

市面上的一些Android教程大多都是教的是为每种dpi都出一套图片资源,这个固然是一种解决办法,但同时也是一种非常笨的方法,为美工或者设计增加了不少的工作量不说,同时也会让你的apk包变的很大。那么有没有什么好的方法既能保证屏幕适配,又可以最小占用设计资源,同时最好又只使用一套dpi的图片资源呢?下面就来讲解下项目中总结出来的这个方法。

首先必须清楚一个自动渲染的概念,Android SDK会自动屏幕尺寸选择对应的资源文件进行渲染,如SDK检测到你手机dpi是160的话会优先到drawable-mdpi文件夹下找对应的图片资源,注意只是优先,假设你手机dpi是160,但是你只在xhpdi文件夹下有对应的图片资源文件,程序一样可以正常运行。所以理论上来说只需要提供一种规格的图片资源就ok了,如果只提供ldpi规格的图片,对于大分辨率的手机如果把图片放大就会不清晰,所以需要提供一套你需要支持的最大dpi的图片,这样即使用户的手机分辨率很小,这样图片缩小依然很清晰。

xhdpi成为首选
上面说了只需要提供一套大的dpi的图片就ok了,现在市面手机分辨率最大可达到1080X1920的分辨率,如Nexus5,dpi属于xxhdpi,但是毕竟还没普及,目前市面上最普遍的高端机的分辨率还多集中在720X1080范围,也就是多集中在xhdpi,所以目前来看xhpdi规格的图片成为了首选。当然随着技术规格的提高以后发展,以后可能市场上xxdpi的手机会越来越普遍,但这是后话。

设计资源紧张怎么办?
在现在的App开发中,基本都会有iOS和Android版本,有些公司为了保持App不同版本的体验交互一致,还有些公司的设计资源可能比较紧张,这些情况下iOS和Android版本基本是一个设计师主导,而大多数情况下设计师可能更会以iPhone手机为基础进行设计,包括后期的切图之类的。这个时候身为Android开发人员你是否还要求设计师单独为Android端切一套图片资源呢?这会让你们的设计师崩溃的,下面就来告诉一个项目中总结的更棒的方法。

相信设计师们一般都会用最新的iPhone5(5s和5的尺寸以及分辨率都一样)来做原型设计,而iPhone5的屏幕分辨率为640X1164, 屏幕尺寸为4英寸,根据勾股定理(a^2 + b^2 = c2)6402+1164^2=1764496, 然后再对其开根号可求出屏幕对角线的分辨率为:1328,除以4可得出iphone5的dpi:1328/4≈332 可以看出iPhone5的屏幕的dpi约等于320, 刚好属于xhdpi,所以你可以很自豪的像你们的设计师说不用专门为Android端切图,直接把iPhone的那一套切好的图片资源放入drawable-xhdpi文件夹里就ok了。

以下例子参考
Android总结之drawable(hdpi,mdpi,ldpi)文件夹的使用
Android drawable微技巧,你所不知道的drawable的那些细节

图1 图2

出现图二的原因是将放在hdpi下的图片放到了默认的文件夹下

本身图片是同一张图片,由于没有在hdpi文件夹中找到对应图片,系统在默认文件夹下找见了图片资源,但是这时系统会认为改图适用于中等分辨率的屏幕上,如果直接放到高分辨率的手机上不能适配,所以系统会自动的将图片放大,所以虽然是同一张图片,但是现实出来就一个正常效果,一个放大效果。

同理,如果同一张图片,放置在ldpi的文件夹下,在低分辨率的手机上显示正常,但是如果放在hdpi文件夹中,系统认为该图是为高分辨率显示的,要将图片缩小处理,所以显示出来的效果就是图变小了。

所以我们在平时要注意,明明都是一张图片,只是放在不同的文件夹中,显示出来的效果就很不同,原因就是我们对Android还不够了解。

更多相关文章

  1. Android(安卓)ScrollView 中放入 ImageView 的出现上下空白
  2. 简单的android折线图绘制
  3. Android(安卓)5.0 API新增和改进
  4. android悬浮窗--获取内存
  5. Android(安卓)icon 不同屏幕下尺寸
  6. Android(安卓)ListView从网络获取图片及文字显示
  7. 【转】Android自适应不同分辨率或不同屏幕大小的layout布局(横屏
  8. 网络编程
  9. ImageView的android:scaleType属性和 src、Background之前的区别

随机推荐

  1. 2013.12.05(5)——— android ViewPagerInd
  2. Android解决NDK not configured问题
  3. android 框架
  4. 读取指定路径数据库的方法
  5. Android横屏,全屏设置
  6. Android保持背光常亮的设置方法
  7. android跳转到微信小程序
  8. android 长按菜单
  9. AndFire防火墙1.2版本发布
  10. [CSDN]Android应用程序启动过程源代码分