本文來自 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();
主要是找mTmpPoint 的y坐标public int getHeight() { synchronized (mTmpPoint) { long now = SystemClock.uptimeMillis(); if (now > (mLastGetTime+20)) { getSizeInternal(mTmpPoint, true); mLastGetTime = now; } return mTmpPoint.y; } }
然後我們發現通過CompatibilityInfo對象設定metrics是一種方法,另一種是getRawHeight()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); } }
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; }
看下Resource類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; }
看到updateConfiguration(config, metrics);方法public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config, CompatibilityInfo compInfo) { mAssets = assets; mMetrics.setToDefaults(); mCompatibilityInfo = compInfo; updateConfiguration(config, metrics); assets.ensureStringBlocks(); }
/** * 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的代碼才知道。
螢幕分辨率的問題就先介紹到這兒。