測(cè)量View(一):創(chuàng)建View并測(cè)量 http://www.reibang.com/p/4fb206b947ee
測(cè)量View(二):測(cè)量寬高及真實(shí)寬高 http://www.reibang.com/p/18540e62ae3a
現(xiàn)在我們可以解決在 測(cè)量View(一):創(chuàng)建View并測(cè)量 中的問題了
調(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();
}
結(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.reibang.com/p/effe9b4333de
簡(jiǎn)單說就是調(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();
}
});
}
問題解決
方法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í)獲得寬高肯定沒問題。
方法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();
}
});
}
沒毛病萌壳,以上三種方法都是打時(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
查看原代碼:調(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();
}
設(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();
}
(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();
}
(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();
}
測(cè)試手機(jī)當(dāng)前的density為3.0 densityDpi為480
手動(dòng)測(cè)量得到測(cè)量的寬高袱瓮,而真實(shí)的寬高都是0,沒毛病
注意:所有的View在measure()時(shí)都與最小寬高及背景有關(guān)嗎?答案是否.要看具體的View中onMeasure()方法的定義
以上measure方法可以將View加到主布局中,也可以不加,都可以獲得測(cè)量寬高