首页 > 代码库 > <html>
<html>
转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/50596463;
本文出自:【Kevin.zhou的博客】
前言:android数以千计的分辨率令我们开发人员头痛不已。那么我们能不能解开它的面纱来赞赏一下它的本质呢?下面就带大家进行这么一场美妙的观光。
一、概述
Android的屏幕适配是一个比較受关注的问题,再加上UI、UE通常是依照IOS出一套然后Android也是对比着去做,给美工小妹妹想要讲清楚dp是一件比登天还难的事情。先来了解下这几个点位之间的关系。
二、 PX、PT、PPI、DPI、DP
术语 | 说明 | 备注 |
PX | (pixel),像素。屏幕上显示数据的最主要的点 | |
PT | (point), 点。印刷行业经常使用单位 | 1pt=1/72英寸 |
PPI | (pixel per inch)。每英寸像素数 | |
DPI | (dot per inch),每英寸点数 | |
DP | 即dip(Density-independent pixel), 设备独立像素 | 1dp=160dpi时1px长度 |
当中px, pt, dp为长度单位,ppi和dpi为密度单位。安卓端屏幕大小各不同样,依据其像素密度,分为下面几种规格:
dp为安卓开发时的长度单位。依据不同的屏幕分辨率,与px有不同的相应关系。
三、获取屏幕宽高
public static int getScreenHeight1(Activity activity) { return activity.getWindowManager().getDefaultDisplay().getHeight(); }
public static int getScreenHeight2(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.heightPixels; }
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) public static int getScreenHeight3(Activity activity) { Point point = new Point(); activity.getWindowManager().getDefaultDisplay().getSize(point); return point.y; }在 Android 4.2(Api17) 之后提供了例如以下方法,与第三种类似也是将数据封装到Point中。然后返回款高度信息。
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static int getScreenHeight4(Activity activity) { Point realSize = new Point(); activity.getWindowManager().getDefaultDisplay().getRealSize(realSize); return realSize.y; }
那么我们执行一把,看下获取的详细信息。下面为MI3和海尔平板(S1001LS)获取的数据:
在MI3上四个方法获取到的数据都为1920px,可是在海尔平板(S1001LS)上面前三个为1848px。最后一个为1920px。出现了分歧,我们看官方说分辨率是多少:
事实上是因为包不包括底部的导航栏的原因。
通过查找发现。在Android 4.0(Api14)就提供了getRealSize()这种方法,仅仅只是是系统隐藏了,我们不能直接去调用。那么能不能通过反射的方式来使用呢?
public static int getScreenHeight5(Activity activity) { Point realSize = new Point(); Display display = activity.getWindowManager().getDefaultDisplay(); try { Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize); } catch (Exception e) { e.printStackTrace(); } return realSize.y; }
/** * Gets the raw width of the display, in pixels. * <p> * The size is adjusted based on the current rotation of the display. * </p> * @hide */ public int getRawHeight() { int h = getRawHeightNative(); if (DEBUG_DISPLAY_SIZE) Slog.v( TAG, "Returning raw display height: " + h); return h; } private native int getRawWidthNative();当然我们能够通过反射的方式来调用它:
public static int getScreenHeight6(Activity activity) { int heightPixels = 0; Display display = activity.getWindowManager().getDefaultDisplay(); try { heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display); } catch (Exception e) { e.printStackTrace(); } return heightPixels; }
Android 版本号 | 版本 | getRawHeight() | getRealSize(Point p) |
Android 3.2 | 13 | 包括(隐藏) | |
Android 4.0,4.0.1,4.0.2 | 14 | 包括(隐藏) | 包括(隐藏) |
Android 4.0.3,4.0.4 | 15 | 包括(隐藏) | 包括(隐藏) |
Android 4.1,4.1.1 | 16 | 包括(隐藏) | 包括(隐藏) |
Android 4.2,4.2.2 | 17 | 包括(隐藏) | 包括 |
... ... | ... ... | ... ... | ... ... |
综上,我们能够得到一个比較完整的获取系统屏幕高度的方法:
public int getRealHeight(Activity activity) { int heightPixels = 0; Display display = activity.getWindowManager().getDefaultDisplay(); final int VERSION = Build.VERSION.SDK_INT; if(VERSION < 13) { display.getHeight(); }else if (VERSION == 13) { try { heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display); } catch (Exception e) { } } else if (VERSION >= 14 && VERSION < 17) { Point realSize = new Point(); try { Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize); heightPixels = realSize.y; } catch (Exception e) { } } else { Point realSize = new Point(); display.getRealSize(realSize); heightPixels = realSize.y; } return heightPixels; }简化一下就是:
public int getRealHeight(Activity activity) { int heightPixels = 0; Display display = activity.getWindowManager().getDefaultDisplay(); final int VERSION = Build.VERSION.SDK_INT; if(VERSION < 13) { display.getHeight(); }else if (VERSION == 13) { try { heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(display); } catch (Exception e) { } } else { Point realSize = new Point(); try { Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize); heightPixels = realSize.y; } catch (Exception e) { } } return heightPixels; }
四、获取屏幕尺寸
/** * The exact physical pixels per inch of the screen in the X dimension. */ public float xdpi; /** * The exact physical pixels per inch of the screen in the Y dimension. */ public float ydpi;没错,这就是我们要找的在宽度和高度上的ppi(每英寸内的像素点数目)。
/** * 获取屏幕宽度ppi * * @param activity * @return 屏幕宽度ppi */ public static float getWidthPpi(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.xdpi; }
/** * 获取屏幕高度ppi * * @param activity * @return 屏幕高度ppi */ public static float getHeightPpi(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.ydpi; }那么获取宽高的物理尺寸也就简单了:
/** * 获取屏幕宽度物理尺寸 * * @param activity * @return */ public static float getWidthInch(Activity activity) { int realWidth = getRealWidth(activity); return (float)realWidth / getWidthPpi(activity); }
/** * 获取屏幕高度物理尺寸 * * @param activity * @return */ public static float getHeightInch(Activity activity) { int realHeight = getRealHeight(activity); return (float)realHeight / getHeightPpi(activity); }依据勾股定理。宽度和高度的尺寸都知道了,对角线的长度就是长度平方加上高度平方再开平方:
/** * 获取屏幕物理尺寸 * * @param activity * @return 屏幕物理尺寸 */ public static float getScreenInch(Activity activity) { return (float)Math.sqrt(Math.pow(getWidthInch(activity), 2) + Math.pow(getHeightInch(activity), 2)); }
五、获取长宽DP
首先通过代码得到dp和ppi(dpi)的相应关系:
/** * 获取屏幕密度 * * @return */ public static float getScreenDensity(Activity activity) { DisplayMetrics displayMetrics = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.density; }然后用屏幕宽高除以 屏幕密度就是宽高上的dp数目:
/** * 获取屏幕可操作区域宽度dp数目 * * @param activity * @return */ public static float getScreenWidthDp(Activity activity) { return getScreenWidth(activity) / getScreenDensity(activity); }
/** * 获取屏幕高度可操作区域dp数目 * * @param activity * @return */ public static float getScreenHeightDp(Activity activity) { return getScreenHeight(activity) / getScreenDensity(activity); }
/** * 获取屏幕真实宽度dp数目 * * @param activity * @return */ public static float getRealWidthDp(Activity activity) { return getRealWidth(activity) / getScreenDensity(activity); }
/** * 获取屏幕真实高度dp数目 * * @param activity * @return */ public static float getRealHeightDp(Activity activity) { return getRealHeight(activity) / getScreenDensity(activity); }
六、推断是手机还是平板
/** * 推断屏幕是否大于6英寸 * * @param activity * @return */ public static boolean isMoreThan6Inch(Activity activity) { return getScreenInch(activity) >= 6.0; }第三种推断是否为大尺寸设备:
/** * 推断设备是否为大尺寸屏幕 * * @param context * @return */ public static boolean isScreenSizeLarge(Context context) { return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; }我们开看下SCREENLAYOUT_SIZE_LARGE 是怎么定义的:
/** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK} * value indicating the screen is at least approximately 480x640 dp units, * corresponds to the * <a href=http://www.mamicode.com/"{@docRoot}guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large>能够看到是推断的屏幕高度和宽度的dp数目。他要求最小为 480X640 dp,我认为最好这两个都满足才是平板:/** * 推断设备是否为平板 * * @param activity * @return true 平板; * false 手机; */ public static boolean isTablet(Activity activity) { return isMoreThan6Inch(activity) && isScreenSizeLarge(activity); }七、源代码及演示样例
给大家提供一个github的地址: Android-Utils 中的 ScreenUtil.java Adroid-Utils是我想把之前的工具类整理下,还在完好中,大家有好的想法能够给我留言。共同进步!另外,欢迎 star or f**k me on github!结语:
事实上我们在开发中还比較在意的一个问题是:
就是我要写多少才他么是真正的占屏幕宽度的一半。!。兴许打算做个工具来处理这些烦人的东西。要过春节了还他么感冒了,加上一些乱七八糟的事情,近期好不爽。牢骚发完了,该干嘛干嘛去!<link rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=1.0" />
cdnversion=‘ + ~(-new Date() / 36e5)];</script>
发表评论
xuehuayous
等级:
排名:千里之外
- 我的GitHub
欢迎Follow、Fork、Star
- 文章分类
- Java0基础与加强(13)
- 开源框架分析(10)
- 设计模式(0)
- 原生控件分析(2)
- 算法(1)
- 个人开源框架(2)
- Android(12)
- 阅读排行
- Android 拍照、选择图片并裁剪(23300)
- Android UltimateRecyclerView优雅地使用RecyclerView(16242)
- Android PullToRefresh 分析之四、扩展RecyclerView(10139)
- Android RecyclerView加入头部和尾部(8805)
- Android 上传图片到JavaWebserver(7615)
- Java 算法 JSON Bean相互转化及JSON生成实体类(5696)
- Android PullToRefresh 分析之中的一个、初识PullToRefresh(4981)
- Android PullToRefresh 全然解析(4687)
- Android PullToRefresh 分析之五、扩展刷新载入样式(4387)
- Android 打造底部导航控件(4338)
- 文章存档
- 2017年02月(1)
- 2017年01月(1)
- 2016年10月(1)
- 2016年09月(1)
- 2016年06月(1)
- 2016年05月(2)
- 2016年04月(1)
- 2016年03月(1)
- 2016年02月(2)
- 2016年01月(4)
- 2015年12月(6)
- 2015年04月(2)
- 2014年12月(4)
- 2014年10月(1)
- 2014年04月(1)
- 2014年03月(13)
- 评论排行
- Android 拍照、选择图片并裁剪(33)
- Android PullToRefresh 分析之四、扩展RecyclerView(15)
- Android RecyclerView加入头部和尾部(12)
- Android PullToRefresh 分析之五、扩展刷新载入样式(10)
- Android PullToRefresh 全然解析(9)
- Android UltimateRecyclerView优雅地使用RecyclerView(6)
- Android 关于屏幕的一些事儿(3)
- Android 上传图片到JavaWebserver(3)
- Android 手把手教你开发轮转大图控件(2)
- Android LayoutInflater源代码解析(1)
- 最新评论
-
Android UltimateRecyclerView优雅地使用RecyclerView
imilyyan回复:
请问下在CoordinatorLayout的布局下,加入了toolbar和UltimateRecyc...
-
Android PullToRefresh 分析之五、扩展刷新载入样式
Jack_lyj回复:
新手请教:LoadingLayoutBase在哪能看到都做了什么啊,急急急,谢谢
-
Android PullToRefresh 分析之五、扩展刷新载入样式
Jack_lyj回复:
新手请教:LoadingLayoutBase在哪能看到都做了什么啊,谢谢
-
Android 拍照、选择图片并裁剪
zb412646700回复:
主要是引用uCrop实现图片剪辑,不是必需搞注解。抽象。接口这些东西。
。
。不但显示不出自己的水平,反而...
-
Android 拍照、选择图片并裁剪
zb412646700回复:
主要是引用uCrop实现图片剪辑,不是必需搞注解,抽象,接口这些东西。
。。
不但显示不出自己的水平,反而...
-
Android 拍照、选择图片并裁剪
u012534883回复:
博主你好,代码我已经执行了,如今我发现不管设置withAspectRatio多少,裁剪框始终是一样宽...
-
Android 拍照、选择图片并裁剪
u012534883回复:
博主你好。代码我已经执行了,如今我发现不管设置withAspectRatio多少,裁剪框始终是一样宽...
-
Android 拍照、选择图片并裁剪
u012534883回复:
博主你好。代码我已经执行了,如今我发现不管设置withAspectRatio多少,裁剪框始终是一样宽...
-
Android 拍照、选择图片并裁剪
jifashi4回复:
没有jar包吗?
-
Android PullToRefresh 分析之四、扩展RecyclerView
u014187519回复:
recycleView没有setAdapter方法和setLayoutManager是什么情况啊?
-
- 我的GitHub
- 文章分类
- 阅读排行
- 文章存档
- 评论排行
- 最新评论
75eacd8></script>