一:自定义MyImageView继承ImageView
/**
* 这个类纯粹是为了看到控件的onMeasure方法和onDraw方法的执行情况
* 任何控件都是同一个道理
* @author Administrator
*
*/
public class MyImageView extends ImageView {
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 测量当前控件获取精确的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
System.out.println("onMeasure 我被调用了"+System.currentTimeMillis());
}
/**
* 在当前控件的父控件中画出当前控件
*/
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
System.out.println("onDraw 我被调用了"+System.currentTimeMillis());
}
}
二:布局文件
<com.yin.test.MyImageView
android:id="@+id/iv"
android:layout_below="@id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android_normal"/>
三:获取宽高的三种方法
public class MainActivity extends Activity {
/**
* 方法调用顺序测试
*/
// @Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
// MyImageView iv = (MyImageView) findViewById(R.id.iv);
// System.out.println("执行完毕.."+System.currentTimeMillis());
// /**
// * 执行结果
// 执行完毕..1435593788788
// onMeasure 我被调用了1435593788812
// onMeasure 我被调用了1435593788812
// onMeasure 我被调用了1435593788851
// onMeasure 我被调用了1435593788851
// onDraw 我被调用了1435593788853
// 结果分析:因为等onCreate方法执行完后,控件才开始度量长宽,因此,无法再onCreate方法中获取控件的长和宽
// */
// }
/**
* 获取控件宽高的第一种方法
* 执行结果:
* onMeasure 我被调用了1435594709480
宽:242,高:245**
执行完毕..1435594709481
onMeasure 我被调用了1435594709591
onMeasure 我被调用了1435594709592
onMeasure 我被调用了1435594710416
onMeasure 我被调用了1435594710416
onDraw 我被调用了1435594710419
*/
// @Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
// MyImageView imageView = (MyImageView) findViewById(R.id.iv);
// int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
// int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
// imageView.measure(w, h);
// int height =imageView.getMeasuredHeight();
// int width =imageView.getMeasuredWidth();
// System.out.println("宽:"+width+",高:"+height+"**");
//
// System.out.println("执行完毕.."+System.currentTimeMillis());
// }
/**
* 获取控件宽高的第二种方法
* 执行结果:
* 执行完毕..1435595234983
onMeasure 我被调用了1435595235018
onMeasure 我被调用了1435595235019
宽:242,高:245**
onMeasure 我被调用了1435595235094
onMeasure 我被调用了1435595235094
宽:242,高:245**
onDraw 我被调用了1435595235097
结果分析:先执行完onCreate方法再执行onMeasure,说明该方法是通过回调的方式获取控件的宽高,且会多次获取宽高
*/
// @Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
// final MyImageView imageView = (MyImageView) findViewById(R.id.iv);
// ViewTreeObserver vto = imageView.getViewTreeObserver();
// vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
// public boolean onPreDraw() {
// int height = imageView.getMeasuredHeight();
// int width = imageView.getMeasuredWidth();
// System.out.println("宽:"+width+",高:"+height+"**");
// return true;
// }
// });
// System.out.println("执行完毕.."+System.currentTimeMillis());
// }
/**
* 获取控件宽高的第三种方法
* 执行结果:
* 执行完毕..1435595905110
onMeasure 我被调用了1435595905202
onMeasure 我被调用了1435595905203
高:245,宽:242
onMeasure 我被调用了1435595905388
onMeasure 我被调用了1435595905389
onDraw 我被调用了1435595905391
onDraw 我被调用了1435595908050
结果分析:该方法与方法二大致相同,都是通过回调的方式,在onCreate执行完后,再获取控件的宽高,且只获取一次宽高
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyImageView imageView = (MyImageView) findViewById(R.id.iv);
ViewTreeObserver vto2 = imageView.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
System.out.println("\n\n"+"高:"+imageView.getHeight()+",宽:"+imageView.getWidth());
}
});
System.out.println("执行完毕.."+System.currentTimeMillis());
}
}
四:第三种方法的总结
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (MyImageView) findViewById(R.id.iv);
System.out.println(
"\n\n"+"onCreate方法中调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+
",onCreate方法中调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);
System.out.println(
"\n\n"+"onCreate方法中调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+
",onCreate方法中调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());
tv = (TextView) findViewById(R.id.tv);
System.out.println(
"onCreate方法中调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+
",onCreate方法中调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);
System.out.println(
"onCreate方法中调用getWidth()时TextView的宽30dp:"+tv.getWidth()+
",onCreate方法中调用getHeight()方法TextView的高60dp:"+tv.getHeight());
LayoutParams lp = tv.getLayoutParams();
lp.width = 200;
lp.height = 400;
tv.setLayoutParams(lp);
System.out.println("------------------------onCreate中---------------------------------");
ViewTreeObserver vto2 = imageView.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
System.out.println(
"\n\n"+"onCreate方法执行完成后调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+
",onCreate方法执行完成后调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);
System.out.println(
"\n\n"+"onCreate方法执行完成后调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+
",onCreate方法执行完成后调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());
System.out.println(
"onCreate方法执行完成后调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+
",onCreate方法执行完成后调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);
System.out.println(
"onCreate方法执行完成后调用getWidth()时TextView的宽30dp:"+tv.getWidth()+
",onCreate方法执行完成后调用getHeight()方法TextView的高60dp:"+tv.getHeight());
System.out.println("------------------------onCreate后---------------------------------");
// ivHeight = imageView.getHeight();
// ivWidth = imageView.getWidth();
// LayoutParams lp = tv.getLayoutParams();
// lp.width = 100;
// lp.height = 200;
// lp.width = imageView.getWidth();
// lp.height = imageView.getHeight();
// tv.setLayoutParams(lp);
// tv.setWidth(imageView.getWidth());这种方式无效
// tv.setHeight(imageView.getHeight());
}
});
System.out.println("执行完毕.."+System.currentTimeMillis());
}
@Override
protected void onStart() {
super.onStart();
System.out.println(
"\n\n"+"onStart方法执行完成后调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+
",onStart方法执行完成后调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);
System.out.println(
"\n\n"+"onStart方法执行完成后调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+
",onStart方法执行完成后调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());
System.out.println(
"onStart方法执行完成后调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+
",onStart方法执行完成后调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);
System.out.println(
"onStart方法执行完成后调用getWidth()时TextView的宽30dp:"+tv.getWidth()+
",onStart方法执行完成后调用getHeight()方法TextView的高60dp:"+tv.getHeight());
System.out.println("------------------------onStart中---------------------------------");
}
@Override
protected void onResume() {
super.onResume();
System.out.println(
"\n\n"+"onResume方法执行完成后调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+
",onResume方法执行完成后调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);
System.out.println(
"\n\n"+"onResume方法执行完成后调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+
",onResume方法执行完成后调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());
System.out.println(
"onResume方法执行完成后调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+
",onResume方法执行完成后调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);
System.out.println(
"onResume方法执行完成后调用getWidth()时TextView的宽30dp:"+tv.getWidth()+
",onResume方法执行完成后调用getHeight()方法TextView的高60dp:"+tv.getHeight());
System.out.println("------------------------onResume中---------------------------------");
}
第三种方法运行结果规律:
规律一:
onCreate()中:
View.getLayoutParams().width/height:
如果在布局文件中View的width/height是具体的值(dp/px)则可以取到,且取值结果是像素(如果是dp则会自动转换为px);
如果在布局文件中View的width/height不是具体的值,而是wrap_content/fill_parent等时,则取不到值,且结果是负数(-2?)
View.getWidth()/getHeight():
不论布局文件中View的width/height是不是具体的值,其结果都是0,即取不到值。
View.getLayoutParams().width/height:
如果在布局文件中View的width/height是具体的值(dp/px)则可以取到,且取值结果是像素(如果是dp则会自动转换为px);
如果在布局文件中View的width/height不是具体的值,而是wrap_content/fill_parent等时,则取不到值,且结果是负数(-2?)
View.getWidth()/getHeight():
不论布局文件中View的width/height是不是具体的值,其结果都是0,即取不到值。
规律二:
onStart()中:
情况和onCreate()方法相同,且在OnGlobalLayoutListener.onGlobalLayout()方法之前执行。
情况和onCreate()方法相同,且在OnGlobalLayoutListener.onGlobalLayout()方法之前执行。
规律三:
onResume()中:
情况和onCreate()方法相同,且在OnGlobalLayoutListener.onGlobalLayout()方法之前执行。
情况和onCreate()方法相同,且在OnGlobalLayoutListener.onGlobalLayout()方法之前执行。
规律四:
OnGlobalLayoutListener.onGlobalLayout()中:
View.getLayoutParams().width/height:和onCreate()方法相同
如果在布局文件中View的width/height是具体的值(dp/px)则可以取到,且取值结果是像素(如果是dp则会自动转换为px);
如果在布局文件中View的width/height不是具体的值,而是wrap_content/fill_parent等时,则取不到值,且结果是负数(-2?)
View.getWidth()/getHeight():
不论布局文件中View的width/height是不是具体的值,都能取到值,且结果的单位是像素
View.getLayoutParams().width/height:和onCreate()方法相同
如果在布局文件中View的width/height是具体的值(dp/px)则可以取到,且取值结果是像素(如果是dp则会自动转换为px);
如果在布局文件中View的width/height不是具体的值,而是wrap_content/fill_parent等时,则取不到值,且结果是负数(-2?)
View.getWidth()/getHeight():
不论布局文件中View的width/height是不是具体的值,都能取到值,且结果的单位是像素