美文网首页
测量View(三):获得测量宽高及真实宽高

测量View(三):获得测量宽高及真实宽高

作者: MinicupSimon | 来源:发表于2017-08-17 00:51 被阅读0次

    测量View(一):创建View并测量 http://www.jianshu.com/p/4fb206b947ee
    测量View(二):测量宽高及真实宽高 http://www.jianshu.com/p/18540e62ae3a

    现在我们可以解决在 测量View(一):创建View并测量 中的问题了

    调用View的measure 及 layout方法便可获得测量宽高及真实宽高

    方法1:View.post()

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
    
            //将View加到根视图中
            mRoot.addView(view);
    
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    
    Paste_Image.png

    结果怎么还是0.

    查看addView()代码:

    public void addView(View child, int index, LayoutParams params) {
           ...
            requestLayout();
           ...
        }
    

    之前学习自定义View时,认为父布局requestLayout后会重新遍历子布局的measure及layout方法
    既然调用了measure, layout方法,为何获取不到测量的宽高,真实的宽高。

    以下这篇分析了requestLayout方法
    http://www.jianshu.com/p/effe9b4333de
    简单说就是调用requestLayout后,遍历子布局的操作是在分线程进行的。

    知道了原因,上代码

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
    
            mRoot.addView(view);
    
            view.post(new Runnable() {
                @Override
                public void run() {
                    int width = view.getWidth();
                    int height = view.getHeight();
                    int measuredWidthAndState = view.getMeasuredWidthAndState();
                    int measuredWidth = view.getMeasuredWidth();
                    int measuredHeight = view.getMeasuredHeight();
                    int measuredHeightAndState = view.getMeasuredHeightAndState();
                }
            });
      }
    
    Paste_Image.png

    问题解决

    方法2:onWindowFocusChanged()

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
            mRoot.addView(view);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    

    onWindowFocusChanged()方法在View的onSizeChanged()后调用。此时View的宽高都已确认
    此时获得宽高肯定没问题。

    Paste_Image.png

    方法3:onClick()中获得宽高

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
            mRoot.addView(view);
    
            mRoot.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int width = view.getWidth();
                    int height = view.getHeight();
                    int measuredWidthAndState = view.getMeasuredWidthAndState();
                    int measuredWidth = view.getMeasuredWidth();
                    int measuredHeight = view.getMeasuredHeight();
                    int measuredHeightAndState = view.getMeasuredHeightAndState();
                }
            });
        }
    
    Paste_Image.png

    没毛病,以上三种方法都是打时间差

    方法4 网上有一种方法:手动measure()

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
            mRoot.addView(view);
            view.measure(0, 0);
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    

    这里的mesure(0, 0)相当于:

            int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);//0
            int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);//0
            view.measure(widthSpec, heightSpec);
    

    但是sorry,结果还是0

    Paste_Image.png

    查看原代码:调用了View的onMeasure()方法

        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                    getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
        }
    

    getSuggestedMinimumWidth()

        protected int getSuggestedMinimumWidth() {
            return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
        }
    

    getSuggestedMinimumHeight()

        protected int getSuggestedMinimumHeight() {
            return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
    
        }
    

    以上发现View的宽高与mMinWidth 及 背景的宽高有关系

    修改代码:

    设置最小宽高
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
    
            view.setMinimumWidth(100);
            view.setMinimumHeight(200);
    
            mRoot.addView(view);
    
            view.measure(0, 0);
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    
    Paste_Image.png
    设置背景图片

    (1)png图片

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
    
            //drawable-mdpi中的png图片48 * 48
            view.setBackgroundResource(R.drawable.ic_launcher);
            mRoot.addView(view); //加不加都行
    
            Drawable background = view.getBackground();
            int intrinsicWidth = background.getIntrinsicWidth();
            int intrinsicHeight = background.getIntrinsicHeight();
           
    
            view.measure(0, 0);
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    
    Paste_Image.png

    (2)xml自定义Drawable

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
    
    //        drawable-mdpi中自定义的GradientDrawable
    //        <?xml version="1.0" encoding="utf-8"?>
    //        <shape xmlns:android="http://schemas.android.com/apk/res/android">
    //               <solid android:color="@color/colorPrimary" />
    //               <size
    //                       android:width="100dp"
    //                       android:height="100dp" />
    //        </shape>
            view.setBackgroundResource(R.drawable.bitmap);
            mRoot.addView(view); //加不加都行
    
            Drawable background = view.getBackground();
            int intrinsicWidth = background.getIntrinsicWidth();
            int intrinsicHeight = background.getIntrinsicHeight();
            
            view.measure(0, 0);
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    
    Paste_Image.png

    (3)代码定义ShapeDrawable

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mRoot = (LinearLayout) findViewById(R.id.root);
    
            view = new View(this);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(300, 300);
            view.setLayoutParams(layoutParams);
    
            ShapeDrawable drawable = new ShapeDrawable();
            drawable.setIntrinsicHeight(100);
            drawable.setIntrinsicWidth(100);
    
            view.setBackgroundDrawable(drawable);
            mRoot.addView(view);//加不加都可以
    
            Drawable background = view.getBackground();
            int intrinsicWidth = background.getIntrinsicWidth();
            int intrinsicHeight = background.getIntrinsicHeight();
           
            view.measure(0, 0);
            int width = view.getWidth();
            int height = view.getHeight();
            int measuredWidthAndState = view.getMeasuredWidthAndState();
            int measuredWidth = view.getMeasuredWidth();
            int measuredHeight = view.getMeasuredHeight();
            int measuredHeightAndState = view.getMeasuredHeightAndState();
        }
    
    Paste_Image.png

    测试手机当前的density为3.0 densityDpi为480

    手动测量得到测量的宽高,而真实的宽高都是0,没毛病

    注意:所有的View在measure()时都与最小宽高及背景有关吗?答案是否.要看具体的View中onMeasure()方法的定义

    以上measure方法可以将View加到主布局中,也可以不加,都可以获得测量宽高

    相关文章

      网友评论

          本文标题:测量View(三):获得测量宽高及真实宽高

          本文链接:https://www.haomeiwen.com/subject/dngirxtx.html