我们都知道在onCreate()里面获取控件的高度是0,这是为什么呢?我们来看一下示例: 

首先我们自己写一个控件,这个控件非常简单:


01
 public class MyImageView extends ImageView {
 
  
02
  
 
  
03
 public MyImageView(Context context, AttributeSet attrs) {
 
  
04
 super(context, attrs);
 
  
05
 }
 
  
06
 public MyImageView(Context context) {
 
  
07
 super(context);
 
  
08
 }
 
  
09
  
 
  
10
 @Override
 
  
11
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 
  
12
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
  
13
 System.out.println("onMeasure 我被调用了"+System.currentTimeMillis());
 
  
14
 }
 
  
15
  
 
  
16
 @Override
 
  
17
 protected void onDraw(Canvas canvas) {
 
  
18
 super.onDraw(canvas);
 
  
19
 System.out.println("onDraw 我被调用了"+System.currentTimeMillis());
 
  
20
 }
 
  
21
 }
 
布局 
 

 
1
 <com.test.MyImageView
 
  
2
 android:id="@+id/imageview"
 
  
3
 android:layout_width="wrap_content"
 
  
4
 android:layout_height="wrap_content"
 
  
5
 android:src="@drawable/test" />
 
oncreate: 
 

 
1
 @Override
 
  
2
 public void onCreate(Bundle savedInstanceState) {
 
  
3
 super.onCreate(savedInstanceState);
 
  
4
 setContentView(R.layout.main);
 
  
5
 System.out.println("执行完毕.."+System.currentTimeMillis());
 
  
6
 }

结果:

android 获取当前控件的坐标 android获取控件高度_控件


说明等onCreate方法执行完了,我们定义的控件才会被度量(measure),所以我们在onCreate方法里面通过view.getHeight()获取控件的高度或者宽度肯定是0,因为它自己还没有被度量,也就是说他自己都不知道自己有多高,而你这时候去获取它的尺寸,肯定是不行的.

现在碰到这个问题我们不能不解决,在网上找到了如下办法:

现在要讨论的是当我们需要时候使用哪个方法呢?
现在把测试的Activity改成如下:

01
 //------------------------------------------------方法一
 
  
02
 int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
 
  
03
 int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
 
  
04
 imageView.measure(w, h);
 
  
05
 int height =imageView.getMeasuredHeight();
 
  
06
 int width =imageView.getMeasuredWidth();
 
  
07
 textView.append("\n"+height+","+width);
 
  
08
  
 
  
09
  
 
  
10
  
 
  
11
  
 
  
12
 //-----------------------------------------------方法二
 
  
13
 ViewTreeObserver vto = imageView.getViewTreeObserver();
 
  
14
 vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
 
  
15
 public boolean onPreDraw() {
 
  
16
 int height = imageView.getMeasuredHeight();
 
  
17
 int width = imageView.getMeasuredWidth();
 
  
18
 textView.append("\n"+height+","+width);
 
  
19
 return true;
 
  
20
 }
 
  
21
 });
 
  
22
 //-----------------------------------------------方法三
 
  
23
 ViewTreeObserver vto2 = imageView.getViewTreeObserver();
 
  
24
 vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
 
  
25
 @Override
 
  
26
 public void onGlobalLayout() {
 
  
27
 imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
 
  
28
 textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth());
 
  
29
 }
 
  
30
 });

01
 public void onCreate(Bundle savedInstanceState) {
 
  
02
 super.onCreate(savedInstanceState);
 
  
03
 setContentView(R.layout.main);
 
  
04
 final ImageView imageView = (ImageView) findViewById(R.id.imageview);
 
  
05
  
 
  
06
 //------------------------------------------------方法一
 
  
07
 int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
 
  
08
 int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
 
  
09
 imageView.measure(w, h);
 
  
10
 int height =imageView.getMeasuredHeight();
 
  
11
 int width =imageView.getMeasuredWidth();
 
  
12
 textView.append("\n"+height+","+width);
 
  
13
  
 
  
14
 System.out.println("执行完毕.."+System.currentTimeMillis());
 
  
15
 }

接着来看下面几种方式输出结果:  


把测试Activity改成如下:



01
 public void onCreate(Bundle savedInstanceState) {
 
  
02
 super.onCreate(savedInstanceState);
 
  
03
 setContentView(R.layout.main);
 
  
04
 final ImageView imageView = (ImageView) findViewById(R.id.imageview);
 
  
05
 -----------------------------------------------方法二
 
  
06
 ViewTreeObserver vto = imageView.getViewTreeObserver();
 
  
07
 vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
 
  
08
 public boolean onPreDraw() {
 
  
09
 int height = imageView.getMeasuredHeight();
 
  
10
 int width = imageView.getMeasuredWidth();
 
  
11
 textView.append("\n"+height+","+width);
 
  
12
 return true;
 
  
13
 }
 
  
14
 });
 
  
15
 }

结果如下:  


android 获取当前控件的坐标 android获取控件高度_System_02


方法三就不再测试了同方法二!!!

那么方法而和方法三在执行上有什么区别呢?
我们在布局文件中加入一个TextView来记录这个控件的宽高.

1
 <ScrollView
 
  
2
 android:layout_width="wrap_content"
 
  
3
 android:layout_height="wrap_content" >
 
  
4
  
 
  
5
 <TextView
 
  
6
 android:id="@+id/text"
 
  
7
 android:layout_width="wrap_content"
 
  
8
 android:layout_height="wrap_content" />
 
  
9
 </ScrollView>

先来测试方法二:


01
 public void onCreate(Bundle savedInstanceState) {
 
  
02
 super.onCreate(savedInstanceState);
 
  
03
 setContentView(R.layout.main);
 
  
04
 final ImageView imageView = (ImageView) findViewById(R.id.imageview);
 
  
05
 -----------------------------------------------方法二
 
  
06
 ViewTreeObserver vto = imageView.getViewTreeObserver();
 
  
07
 vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
 
  
08
 public boolean onPreDraw() {
 
  
09
 int height = imageView.getMeasuredHeight();
 
  
10
 int width = imageView.getMeasuredWidth();
 
  
11
 textView.append("\n"+height+","+width);
 
  
12
 return true;
 
  
13
 }
 
  
14
 });
 
  
15
 }

android 获取当前控件的坐标 android获取控件高度_控件_03

 


再来测试方法三


01
 public void onCreate(Bundle savedInstanceState) {
 
  
02
 super.onCreate(savedInstanceState);
 
  
03
 setContentView(R.layout.main);
 
  
04
 final ImageView imageView = (ImageView) findViewById(R.id.imageview);
 
  
05
 //-----------------------------------------------方法三
 
  
06
 ViewTreeObserver vto2 = imageView.getViewTreeObserver();
 
  
07
 vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
 
  
08
 @Override
 
  
09
 public void onGlobalLayout() {
 
  
10
 imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
 
  
11
 textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth());
 
  
12
 }
 
  
13
 });
 
  
14
 }

android 获取当前控件的坐标 android获取控件高度_android_04

 


总结:那么需要获取控件的宽高该用那个方法呢?
方法一: 比其他的两个方法多了一次计算,也就是多调用了一次onMeasure()方法,该方法虽然看上去简单,但是如果要目标控件计算耗时比较大的话,不见时使用,如listView等.
方法二,它的回调方法会调用很多次,并且滑动TextView的时候任然会调用,所以不建议使用.
方法三,比较合适.
当然,实际应用的时候需要根据实际情况而定.