本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!
在适配的过程中,有时我们会用到屏幕宽高,那么如何获得屏幕的分辨率?
方法有两种:
第一种是通过WindowManager接口获得Diaplay对象,通过Display对象来获得
WindowManager manager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();DisplayMetrics outMetrics=new DisplayMetrics();
display.getMetrics(outMetrics);screenHeight = outMetrics.heightPixels;
screenWidth = outMetrics.widthPixels;
//screenHeight = display.getHeight();此种方法已废弃
//screenWidth = display.getWidth();此种方法已废弃
或者
从源码上来看,拿height来说:
private final Point mTmpPoint = new Point();
public int getHeight() { synchronized (mTmpPoint) { long now = SystemClock.uptimeMillis(); if (now > (mLastGetTime+20)) { getSizeInternal(mTmpPoint, true); mLastGetTime = now; } return mTmpPoint.y; } }主要是找 mTmpPoint 的y坐标
private void getSizeInternal(Point outSize, boolean doCompat) { try { IWindowManager wm = getWindowManager(); if (wm != null) { wm.getDisplaySize(outSize); CompatibilityInfo ci; if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) { synchronized (mTmpMetrics) { mTmpMetrics.noncompatWidthPixels = outSize.x; mTmpMetrics.noncompatHeightPixels = outSize.y; mTmpMetrics.density = mDensity; ci.applyToDisplayMetrics(mTmpMetrics); outSize.x = mTmpMetrics.widthPixels; outSize.y = mTmpMetrics.heightPixels; } } } else { // This is just for boot-strapping, initializing the // system process before the window manager is up. outSize.x = getRawWidth(); outSize.y = getRawHeight(); } if (false) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Slog.v(TAG, "Returning display size: " + outSize, here); } if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v( TAG, "Returning display size: " + outSize); } catch (RemoteException e) { Slog.w("Display", "Unable to get display size", e); } }
然后我们发现通过CompatibilityInfo对象设置metrics是一种方法,另一种是getRawHeight()
public int getRawHeight() { int h = getRawHeightNative(); if (DEBUG_DISPLAY_SIZE) Slog.v( TAG, "Returning raw display height: " + h); return h; } private native int getRawHeightNative();最终是一native方法,通过底层实现。
方法二:通过Resource对象来获得DisplayMetrics来取得
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
screenHeight = metrics.heightPixels;
screenWidth = metrics.widthPixels;
总体来说,都是要取得DisplayMetrics,那么我们来看看它的构成:
/** * Standard quantized DPI for low-density screens. */ public static final int DENSITY_LOW = 120; /** * Standard quantized DPI for medium-density screens. */ public static final int DENSITY_MEDIUM = 160; /** * Standard quantized DPI for 720p TV screens. Applications should * generally not worry about this density, instead targeting * {@link #DENSITY_XHIGH} for 1080p TV screens. For situations where * output is needed for a 720p screen, the UI elements can be scaled * automatically by the platform. */ public static final int DENSITY_TV = 213; /** * Standard quantized DPI for high-density screens. */ public static final int DENSITY_HIGH = 240; /** * Standard quantized DPI for extra-high-density screens. */ public static final int DENSITY_XHIGH = 320;分别有默认的Density值默认实现方法:
public void setToDefaults() { widthPixels = 0; heightPixels = 0; density = DENSITY_DEVICE / (float) DENSITY_DEFAULT; densityDpi = DENSITY_DEVICE; scaledDensity = density; xdpi = DENSITY_DEVICE; ydpi = DENSITY_DEVICE; noncompatWidthPixels = 0; noncompatHeightPixels = 0; }
一般都要实现下面方面,来获得想要的值
public void setTo(DisplayMetrics o) { widthPixels = o.widthPixels; heightPixels = o.heightPixels; density = o.density; densityDpi = o.densityDpi; scaledDensity = o.scaledDensity; xdpi = o.xdpi; ydpi = o.ydpi; noncompatWidthPixels = o.noncompatWidthPixels; noncompatHeightPixels = o.noncompatHeightPixels; noncompatDensity = o.noncompatDensity; noncompatScaledDensity = o.noncompatScaledDensity; noncompatXdpi = o.noncompatXdpi; noncompatYdpi = o.noncompatYdpi; }看下Resource类
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config, CompatibilityInfo compInfo) { mAssets = assets; mMetrics.setToDefaults(); mCompatibilityInfo = compInfo; updateConfiguration(config, metrics); assets.ensureStringBlocks(); }看到 updateConfiguration(config, metrics);方法
/** * Store the newly updated configuration. */ public void updateConfiguration(Configuration config, DisplayMetrics metrics) { updateConfiguration(config, metrics, null); }
/** * @hide */ public void updateConfiguration(Configuration config, DisplayMetrics metrics, CompatibilityInfo compat) { synchronized (mTmpValue) { if (false) { Slog.i(TAG, "**** Updating config of " + this + ": old config is " + mConfiguration + " old compat is " + mCompatibilityInfo); Slog.i(TAG, "**** Updating config of " + this + ": new config is " + config + " new compat is " + compat); } if (compat != null) { mCompatibilityInfo = compat; } if (metrics != null) { mMetrics.setTo(metrics); }
我们会看到这样的结果,所以在形成Resources的时候,metrics已经写入。
可是刚才我们用的是this.getResouces直接来获得的Resource对象ContextThemeWrapper:
@Override public Resources getResources() { if (mResources != null) { return mResources; } if (mOverrideConfiguration == null) { mResources = super.getResources(); return mResources; } else { Context resc = createConfigurationContext(mOverrideConfiguration); mResources = resc.getResources(); return mResources; } }
主要是在Context里实现,具体怎么实现,估计还是要看native的代码才知道。屏幕分辨率的问题就先介绍到这儿。