测量控件的宽与高

七、使用 View.post() 方法: 
Runnable 对象中的方法会在 View 的 measure、layout 等事件完成后触发。 
UI 事件队列会按顺序处理事件,在 setContentView() 被调用后,事件队列中会包含一个要求重新 layout 的 message,所以任何 post 到队列中的 Runnable 对象都会在 Layout 发生变化后执行。 
该方法只会执行一次,且逻辑简单,建议使用

view.post(new Runnable() { @Override    public void run() {        view.getWidth(); // 获取宽度        view.getHeight(); // 获取高度    }});

一:自定义MyImageView继承ImageView

[java]  view plain  copy
  1. /** 
  2.  * 这个类纯粹是为了看到控件的onMeasure方法和onDraw方法的执行情况 
  3.  * 任何控件都是同一个道理 
  4.  * @author Administrator 
  5.  * 
  6.  */  
  7. public class MyImageView extends ImageView {  
  8.   
  9.     public MyImageView(Context context) {  
  10.         super(context);  
  11.     }  
  12.     public MyImageView(Context context, AttributeSet attrs) {    
  13.         super(context, attrs);    
  14.     }   
  15.     /** 
  16.      * 测量当前控件获取精确的宽和高 
  17.      */  
  18.     @Override  
  19.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  20.         // TODO Auto-generated method stub  
  21.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  22.         System.out.println("onMeasure 我被调用了"+System.currentTimeMillis());  
  23.     }  
  24.     /** 
  25.      * 在当前控件的父控件中画出当前控件 
  26.      */  
  27.     @Override  
  28.     protected void onDraw(Canvas canvas) {  
  29.         // TODO Auto-generated method stub  
  30.         super.onDraw(canvas);  
  31.         System.out.println("onDraw 我被调用了"+System.currentTimeMillis());   
  32.     }  
  33. }  

二:布局文件

[html]  view plain  copy
  1. <com.yin.test.MyImageView   
  2.         android:id="@+id/iv"  
  3.         android:layout_below="@id/tv"  
  4.         android:layout_width="wrap_content"  
  5.         android:layout_height="wrap_content"  
  6.         android:src="@drawable/android_normal"/>  

三:获取宽高的三种方法

[java]  view plain  copy
  1. public class MainActivity extends Activity {  
  2.     /** 
  3.      * 方法调用顺序测试 
  4.      */  
  5. //  @Override  
  6. //  protected void onCreate(Bundle savedInstanceState) {  
  7. //      super.onCreate(savedInstanceState);  
  8. //      setContentView(R.layout.activity_main);  
  9. //      MyImageView iv = (MyImageView) findViewById(R.id.iv);  
  10. //      System.out.println("执行完毕.."+System.currentTimeMillis());   
  11. //      /**  
  12. //       * 执行结果  
  13. //       执行完毕..1435593788788  
  14. //      onMeasure 我被调用了1435593788812  
  15. //      onMeasure 我被调用了1435593788812  
  16. //      onMeasure 我被调用了1435593788851  
  17. //      onMeasure 我被调用了1435593788851  
  18. //      onDraw 我被调用了1435593788853  
  19. //  结果分析:因为等onCreate方法执行完后,控件才开始度量长宽,因此,无法再onCreate方法中获取控件的长和宽  
  20. //       */  
  21. //  }  
  22.     /** 
  23.      * 获取控件宽高的第一种方法 
  24.      * 执行结果: 
  25.      * onMeasure 我被调用了1435594709480 
  26.         宽:242,高:245** 
  27.         执行完毕..1435594709481 
  28.         onMeasure 我被调用了1435594709591 
  29.         onMeasure 我被调用了1435594709592 
  30.         onMeasure 我被调用了1435594710416 
  31.         onMeasure 我被调用了1435594710416 
  32.         onDraw 我被调用了1435594710419 
  33.      */  
  34. //  @Override  
  35. //  protected void onCreate(Bundle savedInstanceState) {  
  36. //      super.onCreate(savedInstanceState);  
  37. //      setContentView(R.layout.activity_main);  
  38. //      MyImageView imageView = (MyImageView) findViewById(R.id.iv);  
  39. //      int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);    
  40. //        int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);    
  41. //        imageView.measure(w, h);    
  42. //        int height =imageView.getMeasuredHeight();    
  43. //        int width =imageView.getMeasuredWidth();    
  44. //        System.out.println("宽:"+width+",高:"+height+"**");    
  45. //            
  46. //        System.out.println("执行完毕.."+System.currentTimeMillis());  
  47. //  }  
  48.       
  49.     /** 
  50.      * 获取控件宽高的第二种方法 
  51.      * 执行结果: 
  52.      *  执行完毕..1435595234983 
  53.         onMeasure 我被调用了1435595235018 
  54.         onMeasure 我被调用了1435595235019 
  55.         宽:242,高:245** 
  56.         onMeasure 我被调用了1435595235094 
  57.         onMeasure 我被调用了1435595235094 
  58.         宽:242,高:245** 
  59.         onDraw 我被调用了1435595235097 
  60.     结果分析:先执行完onCreate方法再执行onMeasure,说明该方法是通过回调的方式获取控件的宽高,且会多次获取宽高 
  61.      */  
  62. //  @Override  
  63. //  protected void onCreate(Bundle savedInstanceState) {  
  64. //      super.onCreate(savedInstanceState);  
  65. //      setContentView(R.layout.activity_main);  
  66. //      final MyImageView imageView = (MyImageView) findViewById(R.id.iv);  
  67. //      ViewTreeObserver vto = imageView.getViewTreeObserver();    
  68. //      vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {    
  69. //          public boolean onPreDraw() {    
  70. //              int height = imageView.getMeasuredHeight();    
  71. //              int width = imageView.getMeasuredWidth();    
  72. //              System.out.println("宽:"+width+",高:"+height+"**");   
  73. //              return true;    
  74. //          }    
  75. //      });  
  76. //      System.out.println("执行完毕.."+System.currentTimeMillis());  
  77. //  }  
  78.       
  79.     /** 
  80.      * 获取控件宽高的第三种方法 
  81.      * 执行结果: 
  82.      *  执行完毕..1435595905110 
  83.         onMeasure 我被调用了1435595905202 
  84.         onMeasure 我被调用了1435595905203 
  85.         高:245,宽:242 
  86.         onMeasure 我被调用了1435595905388 
  87.         onMeasure 我被调用了1435595905389 
  88.         onDraw 我被调用了1435595905391 
  89.         onDraw 我被调用了1435595908050 
  90.     结果分析:该方法与方法二大致相同,都是通过回调的方式,在onCreate执行完后,再获取控件的宽高,且只获取一次宽高 
  91.      */  
  92.     @Override  
  93.     protected void onCreate(Bundle savedInstanceState) {  
  94.         super.onCreate(savedInstanceState);  
  95.         setContentView(R.layout.activity_main);  
  96.         final MyImageView imageView = (MyImageView) findViewById(R.id.iv);  
  97.         ViewTreeObserver vto2 = imageView.getViewTreeObserver();      
  98.         vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {    
  99.             @Override      
  100.             public void onGlobalLayout() {    
  101.                 imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);      
  102.                 System.out.println("\n\n"+"高:"+imageView.getHeight()+",宽:"+imageView.getWidth());    
  103.             }      
  104.         });  
  105.         System.out.println("执行完毕.."+System.currentTimeMillis());  
  106.     }  
  107. }  

四:第三种方法的总结

[java]  view plain  copy
  1. @Override  
  2.     protected void onCreate(Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         setContentView(R.layout.activity_main);  
  5.         imageView = (MyImageView) findViewById(R.id.iv);  
  6.         System.out.println(  
  7.                 "\n\n"+"onCreate方法中调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+  
  8.                 ",onCreate方法中调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);  
  9.           
  10.         System.out.println(  
  11.                 "\n\n"+"onCreate方法中调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+  
  12.                 ",onCreate方法中调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());  
  13.         tv = (TextView) findViewById(R.id.tv);  
  14.         System.out.println(  
  15.                 "onCreate方法中调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+  
  16.                 ",onCreate方法中调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);  
  17.         System.out.println(  
  18.                  "onCreate方法中调用getWidth()时TextView的宽30dp:"+tv.getWidth()+  
  19.                 ",onCreate方法中调用getHeight()方法TextView的高60dp:"+tv.getHeight());  
  20.         LayoutParams lp = tv.getLayoutParams();  
  21.         lp.width = 200;  
  22.         lp.height = 400;  
  23.         tv.setLayoutParams(lp);  
  24.         System.out.println("------------------------onCreate中---------------------------------");  
  25.         ViewTreeObserver vto2 = imageView.getViewTreeObserver();      
  26.         vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {    
  27.   
  28.             @Override      
  29.             public void onGlobalLayout() {    
  30.                 imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);      
  31.                 System.out.println(  
  32.                         "\n\n"+"onCreate方法执行完成后调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+  
  33.                         ",onCreate方法执行完成后调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);  
  34.                   
  35.                 System.out.println(  
  36.                         "\n\n"+"onCreate方法执行完成后调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+  
  37.                         ",onCreate方法执行完成后调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());  
  38.                 System.out.println(  
  39.                         "onCreate方法执行完成后调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+  
  40.                         ",onCreate方法执行完成后调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);  
  41.                 System.out.println(  
  42.                          "onCreate方法执行完成后调用getWidth()时TextView的宽30dp:"+tv.getWidth()+  
  43.                         ",onCreate方法执行完成后调用getHeight()方法TextView的高60dp:"+tv.getHeight());                 
  44.                 System.out.println("------------------------onCreate后---------------------------------");                 
  45.                   
  46. //              ivHeight = imageView.getHeight();  
  47. //              ivWidth = imageView.getWidth();  
  48. //              LayoutParams lp = tv.getLayoutParams();  
  49. //              lp.width = 100;  
  50. //              lp.height = 200;  
  51. //              lp.width = imageView.getWidth();  
  52. //              lp.height = imageView.getHeight();  
  53.                   
  54. //              tv.setLayoutParams(lp);  
  55. //              tv.setWidth(imageView.getWidth());这种方式无效  
  56. //              tv.setHeight(imageView.getHeight());  
  57.             }      
  58.         });  
  59.         System.out.println("执行完毕.."+System.currentTimeMillis());  
  60.     }  
  61.     @Override  
  62.     protected void onStart() {  
  63.         super.onStart();  
  64.         System.out.println(  
  65.                 "\n\n"+"onStart方法执行完成后调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+  
  66.                 ",onStart方法执行完成后调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);  
  67.           
  68.         System.out.println(  
  69.                 "\n\n"+"onStart方法执行完成后调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+  
  70.                 ",onStart方法执行完成后调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());  
  71.         System.out.println(  
  72.                 "onStart方法执行完成后调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+  
  73.                 ",onStart方法执行完成后调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);  
  74.         System.out.println(  
  75.                  "onStart方法执行完成后调用getWidth()时TextView的宽30dp:"+tv.getWidth()+  
  76.                 ",onStart方法执行完成后调用getHeight()方法TextView的高60dp:"+tv.getHeight());                  
  77.         System.out.println("------------------------onStart中---------------------------------");              
  78.     }  
  79.     @Override  
  80.     protected void onResume() {  
  81.         super.onResume();  
  82.         System.out.println(  
  83.                 "\n\n"+"onResume方法执行完成后调用getLayoutParams方法ImageView的宽100dp:"+imageView.getLayoutParams().width+  
  84.                 ",onResume方法执行完成后调用getLayoutParams方法ImageView的高wrap_content:"+imageView.getLayoutParams().height);  
  85.           
  86.         System.out.println(  
  87.                 "\n\n"+"onResume方法执行完成后调用getWidth()时ImageView的宽100dp:"+imageView.getWidth()+  
  88.                 ",onResume方法执行完成后调用getHeight()时ImageView的高wrap_content:"+imageView.getHeight());  
  89.         System.out.println(  
  90.                 "onResume方法执行完成后调用getLayoutParams方法TextView的宽30dp:"+tv.getLayoutParams().width+  
  91.                 ",onResume方法执行完成后调用getLayoutParams方法TextView的高60dp:"+tv.getLayoutParams().height);  
  92.         System.out.println(  
  93.                  "onResume方法执行完成后调用getWidth()时TextView的宽30dp:"+tv.getWidth()+  
  94.                 ",onResume方法执行完成后调用getHeight()方法TextView的高60dp:"+tv.getHeight());                 
  95.         System.out.println("------------------------onResume中---------------------------------");             
  96.     }  
第三种方法运行结果规律:
规律一:
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,即取不到值。
规律二:
onStart()中: 情况和onCreate()方法相同,且在OnGlobalLayoutListener.onGlobalLayout()方法之前执行。
规律三:
onResume()中: 情况和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是不是具体的值,都能取到值,且结果的单位是像素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值