Android螢幕解析度擷取方法--源碼剖析

來源:互聯網
上載者:User

本文來自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的代碼才知道。

螢幕解析度的問題就先介紹到這兒。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.