原文地址:http://blog.csdn.net/canot/article/details/50430998

在oncreate()中无论利用view.getWidth()或是view.getHeiht()还是view.getMeasuredHeight或view.getMeasuredWidth()来获取view的宽和高,看似没有问题,其实他们取得值是0,并不是你想要的结果。这是因为每个布局都要经过如下三个步骤:

测量:onMeasure 设置自己显示在屏幕上的宽高
布局:onLayout 设置自己显示在屏幕上的位置(只有在自定义ViewGroup中才用到)
绘制:onDraw 控制显示在屏幕上的样子(viewgroup没有这个过程)
如上的步骤是异步进行的,在oncreate()中界面处于不可见状态,内存加载组件还没有绘制出来,所以是无法获取他的尺寸。
那如何在绘制组件之前能获取到该组件的尺寸大小呢?
方法一(最常用的方法):

//手动调用测量方法。
//制定测量规则 参数表示size + mode
int width =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
int height =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
view.measure(width,height);
//调用measure方法之后就可以获取宽高。
int height=view.getMeasuredHeight();
int width=view.getMeasuredWidth();

方法二(设置树桩结构监听器):

ViewTreeObserver vto =view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int height =view.getMeasuredHeight();
int width =view.getMeasuredWidth();
}
});

方法三(增加组件绘制之前的监听):

ViewTreeObserver vto =view.getViewTreeObserver();

vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int height =view.getMeasuredHeight();
int width =view.getMeasuredWidth();
}
});

详解View.measure:
measure()方法是实际测量的方法,而在绘制布局过程中调用的onMeasure()只是制定测量规则.
在自定义布局中我们一般重写onMeasure()方法,measure()方法是final的,子类无法重写。
看到measure函数有2个参数,int widthMeasureSpec 和 int heightMeasureSpec表示具体的测量规则。
这两个数值不是普通的数值, 它表示: size + mode
例如:
int widthMeasureSpec= View.MeasureSpec.makeMeasureSpec(1000,View.MeasureSpec.EXACTLY);
int heightMeasureSpec= View.MeasureSpec.makeMeasureSpec(1000,View.MeasureSpec.AT_MOST);
模式分为:
View.MeasureSpec.EXACTLY:表示父视图希望子类的大小是specSize中制定的大小.
View.MeasureSpec.AT_MOST:父试图希望子类的大小最高不超过specSize中制定的大小.
View.MeasureSpec.UNSPECIFIED:父试图不对子类实施任何限制,子试图可以得到自己想得到的任意大小.
需求:
在TextView中通过代码调用setText()动态的设置文本,要求在设置文本之后获取其宽高.
TextView的布局方式为width:match_parent height:wrap_content

    int width=textView.getMeasuredWidth(); // 开始宽度    textView.getLayoutParams().height= ViewGroup.LayoutParams.WRAP_CONTENT;// 高度包裹内容    int widthMeasureSpec=View.MeasureSpec.makeMeasureSpec(width,View.MeasureSpec.EXACTLY);     //宽度是match_parent.即是View.MeasureSpec.EXACTLY    int heightMeasureSpec= View.MeasureSpec.makeMeasureSpec(1000,View.MeasureSpec.AT_MOST);    //让高度最大为1000    textView.measure(widthMeasureSpec, heightMeasureSpec);    return des_content.getMeasuredHeight();

这样就获取到Textview的高的,根据文本的多少获取不同高度。之前很多人可能直接measure(0,0)来测量看,其实就是:
int widthMeasureSpec=View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
int heightMeasureSpec= View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);

利于这个方法为ImageView设置宽高比例显示:

             

通过一个自定义布局把ImageView包裹起来:

重写这个自定义布局的onMeasure()方法修改其测量规则,让其款高按一定比例显示:

int ratio = 2.43
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// widthMeasureSpec 宽度的规则 包含了两部分 模式 值
int widthMode = MeasureSpec.getMode(widthMeasureSpec); // 模式
int widthSize = MeasureSpec.getSize(widthMeasureSpec);// 宽度大小
int width = widthSize - getPaddingLeft() - getPaddingRight();// 去掉左右两边的padding

    int heightMode = MeasureSpec.getMode(heightMeasureSpec); // 模式    int heightSize = MeasureSpec.getSize(heightMeasureSpec);// 高度大小    int height = heightSize - getPaddingTop() - getPaddingBottom();// 去掉上下两边的padding               //如果width是match_parent     if (widthMode == MeasureSpec.EXACTLY            && heightMode != MeasureSpec.EXACTLY) {        // 修正一下 高度的值 让高度=宽度/比例        height = (int) (width / ratio + 0.5f); // 保证4舍五入    } else if (widthMode != MeasureSpec.EXACTLY            && heightMode == MeasureSpec.EXACTLY) {        // 由于高度是精确的值 ,宽度随着高度的变化而变化        width = (int) ((height * ratio) + 0.5f);    }    // 重新制作了新的规则    widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY,            width + getPaddingLeft() + getPaddingRight());    heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY,            height + getPaddingTop() + getPaddingBottom());    super.onMeasure(widthMeasureSpec, heightMeasureSpec);}

更多相关文章

  1. android自定义Adapter
  2. CardView卡片效果
  3. Android(安卓)Camera 二 JNI JAVA和C/CPP图像数据传输流程分析
  4. Android(安卓)官方架构组件(一)——Lifecycle
  5. Android基于Http协议实现文件上传功能的方法
  6. 倒计时效果
  7. SDK is not loaded yet解决方法
  8. 【Android】原生Progress提示
  9. EditText焦点自动带出软键盘问题

随机推荐

  1. Android培训班(28)
  2. android多activity下如何退出整个程序
  3. 布局中嵌套布局!
  4. android上的一个网络接口和图片缓存框架e
  5. Android读取手机文件列表
  6. android刷字体教程
  7. Android获取设备已安装的应用
  8. android 判断字符串是否为空与比对["=="
  9. Android软件集合
  10. Android应用使用百度地图API