測(cè)量View(三):獲得測(cè)量寬高及真實(shí)寬高

測(cè)量View(一):創(chuàng)建View并測(cè)量 http://www.lxweimin.com/p/4fb206b947ee
測(cè)量View(二):測(cè)量寬高及真實(shí)寬高 http://www.lxweimin.com/p/18540e62ae3a

現(xiàn)在我們可以解決在 測(cè)量View(一):創(chuàng)建View并測(cè)量 中的問(wèn)題了

調(diào)用View的measure 及 layout方法便可獲得測(cè)量寬高及真實(shí)寬高

方法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

結(jié)果怎么還是0.

查看addView()代碼:

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

之前學(xué)習(xí)自定義View時(shí),認(rèn)為父布局requestLayout后會(huì)重新遍歷子布局的measure及l(fā)ayout方法
既然調(diào)用了measure, layout方法,為何獲取不到測(cè)量的寬高,真實(shí)的寬高。

以下這篇分析了requestLayout方法
http://www.lxweimin.com/p/effe9b4333de
簡(jiǎn)單說(shuō)就是調(diào)用requestLayout后,遍歷子布局的操作是在分線程進(jìn)行的。

知道了原因,上代碼

    @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

問(wèn)題解決

方法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()后調(diào)用。此時(shí)View的寬高都已確認(rèn)
此時(shí)獲得寬高肯定沒(méi)問(wèn)題。

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

沒(méi)毛病,以上三種方法都是打時(shí)間差

方法4 網(wǎng)上有一種方法:手動(dòng)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)相當(dāng)于:

        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,結(jié)果還是0

Paste_Image.png

查看原代碼:調(diào)用了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());

    }

以上發(fā)現(xiàn)View的寬高與mMinWidth 及 背景的寬高有關(guān)系

修改代碼:

設(shè)置最小寬高
    @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
設(shè)置背景圖片

(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

測(cè)試手機(jī)當(dāng)前的density為3.0 densityDpi為480

手動(dòng)測(cè)量得到測(cè)量的寬高,而真實(shí)的寬高都是0,沒(méi)毛病

注意:所有的View在measure()時(shí)都與最小寬高及背景有關(guān)嗎?答案是否.要看具體的View中onMeasure()方法的定義

以上measure方法可以將View加到主布局中,也可以不加,都可以獲得測(cè)量寬高

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容