我们都知道在onCreate()里面获取控件的高度是0,这是为什么呢?我们来看一下示例:
首先我们自己写一个控件,这个控件非常简单:
[java]
public class MyImageView extends ImageView {

public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyImageView(Context context) {
super(context);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
System.out.println("onMeasure 我被调用了"+System.currentTimeMillis());
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
System.out.println("onDraw 我被调用了"+System.currentTimeMillis());
}

}

布局文件:
[java]
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/test" />

测试的Activity的onCreate():
[java]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
System.out.println("执行完毕.."+System.currentTimeMillis());
}
现在我们现在来看一下结果:

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

现在碰到这个问题我们不能不解决,在网上找到了如下办法:
[java]
//------------------------------------------------方法一
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();
textView.append("\n"+height+","+width);




//-----------------------------------------------方法二
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
textView.append("\n"+height+","+width);
return true;
}
});
//-----------------------------------------------方法三
ViewTreeObserver vto2 = imageView.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth());
}
});

这三个方法是哪里找到现在已经忘了.

现在要讨论的是当我们需要时候使用哪个方法呢?
现在把测试的Activity改成如下:
[java]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView imageView = (ImageView) findViewById(R.id.imageview);

//------------------------------------------------方法一
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();
textView.append("\n"+height+","+width);

System.out.println("执行完毕.."+System.currentTimeMillis());
}

接着来看下面几种方式输出结果:
把测试Activity改成如下:
[java]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView imageView = (ImageView) findViewById(R.id.imageview);
-----------------------------------------------方法二
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
textView.append("\n"+height+","+width);
return true;
}
});
}

结果如下:


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

那么方法而和方法三在执行上有什么区别呢?
我们在布局文件中加入一个TextView来记录这个控件的宽高.
[java]
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

先来测试方法而:
[java]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView imageView = (ImageView) findViewById(R.id.imageview);
-----------------------------------------------方法二
ViewTreeObserver vto = imageView.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = imageView.getMeasuredHeight();
int width = imageView.getMeasuredWidth();
textView.append("\n"+height+","+width);
return true;
}
});
}

结果如下:


我们再来测试方法三
[java]
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView imageView = (ImageView) findViewById(R.id.imageview);
//-----------------------------------------------方法三
ViewTreeObserver vto2 = imageView.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth());
}
});
}

输出结果如下:


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

 

更多相关文章

  1. Android(安卓)Vold和SDIO冲突问题解决方法
  2. android webView 使用方法
  3. Android(安卓)UI 测试框架 Espresso
  4. Android获取当前进程名
  5. Android(安卓)生命周期架构组件使用方法
  6. android彻底杀死当前activity和线程方法
  7. android 如何判断开机完成
  8. Android屏幕适配大法
  9. Android(安卓)左侧滑动窗口打开关闭监测

随机推荐

  1. Android(安卓)Emulator 2.0更新方法
  2. Android(安卓)ExpandableListActivity实
  3. 【转】【Android】开源项目汇总-备用
  4. RxJava学习笔记(Schedulers)
  5. Android(安卓)string-array简单使用
  6. Android类似于滚动的通知栏实现
  7. Android(安卓)6.0添加自定义铃声
  8. Android(安卓)EventLog简介
  9. Android(安卓)XML属性在文档中的位置
  10. RK3288[android 7.1]调试笔记 控制副屏旋