android 测量基础--测量控件宽高以及位置的技巧

1. 获得屏幕的宽高

    private void getWindowHeight() {
        int heightPixels = getResources().getDisplayMetrics().heightPixels;
        int height = getWindowManager().getDefaultDisplay().getHeight();
        Log.e(TAG, "heightPixels = "+heightPixels);
        // output = 1280
        Log.e(TAG, "height = "+height );
        // output = 1280
    }

2. 动态测量--获得控件在屏幕的坐标,可视区域

      观察View的绘制流程,设置OnGlobalLayoutListener监听,布局完成时会调用onGlobalLayout(),在onGlobalLayout()方法里面获取空间的宽和高

android 测量基础--测量控件宽高以及位置的技巧_第1张图片

        // 测量树---------
        mBtnLocation.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                // 控件相对于手机屏幕的位置坐标    
                // 一个控件在整个屏幕中的坐标位置 --(状态栏48px)
                int[] location1 = new int[2];
                mBtnLocation.getLocationOnScreen(location1);
                Log.e(TAG, "getLocationOnScreen : x = "+location1[0]+" y = "+location1[1] );
                // output  x = 40 , y = 200
                int[] location2 = new int[2];
                mBtnLocation.getLocationInWindow(location2);
                Log.e(TAG, "getLocationInWindow : x = "+location2[0]+" y = "+location2[1] );
                // output x = 40 , y = 200

                Rect rect = new Rect();
                mBtnLocation.getWindowVisibleDisplayFrame(rect);
                Log.e("getWindowVisible","矩形左 = "+rect.left+"  矩形上 = "+rect.top +
                        " 矩形右 = "+rect.right +"  矩形下 = "+rect.bottom);
                // output (0,48,720,1280)
                
                // 移除树构建测量 防止内存泄漏-------
                mBtnLocation.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            }
        });

 说明:

OnGlobalLayoutListener 是ViewTreeObserver的内部类,当一个视图树的布局发生改变时,可以被ViewTreeObserver监听到,这是一个注册监听视图树的观察者(observer),在视图树的全局事件改变时得到通知。ViewTreeObserver不能直接实例化,而是通过getViewTreeObserver()获得。

getWindowVisibleDisplayFrame()执行结果均是指当前Window实际的可视区域大小,此处不包含状态栏高度
           getLocationOnScreen getLocationInWindow 得到view在屏幕上的位置,相对屏幕左上角,此处包含了状态栏的偏移了

我们可以比较其bottom,因为都是从屏幕左上角为参照物的

这里提醒一下,如果想拿到控件在屏幕的位置应当在观察树中去获得,假如在onCreate()中去获得,显示的是不当的

    private void originLocation() {
        // 必须等布局完了之后才能
        int[] locations = new int [2];
        llLocation.getLocationOnScreen(locations);
        Log.e(TAG,"x = "+locations[0] ); // x = 0
        Log.e(TAG,"y = "+locations[1] ); // y = 0
    }

 

3. 动态测量 - --  measure(0,0)

开发者手动调用测量方法

    private void getMeasureTextHeight(){
        Log.e(TAG, "measure之前" );
        Log.e(TAG, "宽 = "+mBtnLocation.getMeasuredWidth()+",高 = "+mBtnLocation.getMeasuredHeight());
        mBtnLocation.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
        Log.e(TAG, "measure之后" );
        Log.e(TAG, "宽 = "+mBtnLocation.getMeasuredWidth()+",高 = "+mBtnLocation.getMeasuredHeight());
    }
06-18 15:08:54.967 11070-11070/com.jit.bgwithasset E/位置: measure之前
06-18 15:08:54.967 11070-11070/com.jit.bgwithasset E/位置: 宽 = 0,高 = 0
06-18 15:08:54.968 11070-11070/com.jit.bgwithasset E/位置: measure之后
06-18 15:08:54.968 11070-11070/com.jit.bgwithasset E/位置: 宽 = 208,高 = 96

这位网友讲的很好,链接 

⚠️注意

如果组件的宽度或高度设置为fill_parent或者match_parent。使用getMeasuredHeight 或者 getMeasuredHeight方法获取组件宽度或者高度时,当组件中包含其他子组件时,所获得的实际值是这些组件所占的最小宽度和最小高度。

实验如下

    
        
        
    
    private void getMeasureLinearHeight(){
        Log.e(TAG, "measure之前" );
        Log.e(TAG, "宽 = "+llLocation.getMeasuredWidth()+",高 = "+llLocation.getMeasuredHeight());
        llLocation.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
        Log.e(TAG, "measure之后" );
        Log.e(TAG, "宽 = "+llLocation.getMeasuredWidth()+",高 = "+llLocation.getMeasuredHeight());
    }

  发现了没,测量到的是其子布局的大小哦。

06-18 15:23:53.161 12270-12270/com.jit.bgwithasset E/位置: 宽 = 0,高 = 0
06-18 15:23:53.161 12270-12270/com.jit.bgwithasset E/位置: measure之后
06-18 15:23:53.161 12270-12270/com.jit.bgwithasset E/位置: 宽 = 60,高 = 60

小结 

   当我们使用measure(0,0)的时候,一定要注意大多用于测量view,而不是用于viewGroup布局。假如测量的是VG那么其大小是其子布局所占据的大小。再有如果viewgroup不含有子布局其实是没用的,测量的宽高都是0。

4. 动态测量 --- view.post

    private void getMeasureHeight() {
        mBtnLocation.post(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG, "run: "+ mBtnLocation.getMeasuredHeight());
                Log.e(TAG, "run: "+mBtnLocation.getMeasuredWidth());
                // output width = 208 height = 96
            }
        });
    }

讲的不错的文章

Android 中获取控件宽和高的方法(详细解析)

你可能感兴趣的:(android基础)