• Android屏幕分辨率获取方法--源码剖析


                        

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

    屏幕分辨率的问题就先介绍到这儿。



  • 相关阅读:
    appium 元素定位方法
    Mac 使用MuMu模拟器调试
    渗透测试工具Drozer安装使用(Mac)
    渗透测试工具Drozer安装使用(Windows)
    python虚拟环境搭建
    HDU 6900 Residual Polynomial【分治 NTT】
    CF 1405E Fixed Point Removal【线段树上二分】
    Educational Codeforces Round 41
    Educational Codeforces Round 39
    Educational Codeforces Round 36
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6147355.html
Copyright © 2020-2023  润新知