1. 問題
如何獲取一個控件的長和高,相信很多朋友第一眼看見這個問題都會覺得很簡單,直接在onCreate里面調用getWidth、getMeasuredWidth不就可以獲得了嗎,但是,事實上是並沒有簡單的,不信的話,你可以去試一下,在onCreate里面,你是無法獲得長寬值的,始終為0。
1 package com.himi.test; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.ViewTreeObserver; 7 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 8 import android.widget.Button; 9 10 public class MainActivity extends Activity { 11 12 private Button button; 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 19 button = (Button) findViewById(R.id.button); 20 Log.e("Test", "getWidth寬度:" + button.getWidth()); 21 Log.e("Test", "getHeight高度:" + button.getMeasuredWidth()); 22 } 23 24 }
程序運行結果如下:
2. 原因
這是為什么呢,其實熟悉view繪制流程的朋友應該一眼就看出來了,在onCreate中,我們的控件其實還並沒有畫好,換句話說,等onCreate方法執行完了,我們定義的控件才會被度量(measure),所以我們在onCreate方法里面通過view.getHeight()獲取控件的高度或者寬度肯定是0。
3. 獲取Button的高度、寬度、坐標值:
(1)利用延時(保證onCreate先完成):
1 package com.himi.test; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.ViewTreeObserver; 7 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 8 import android.widget.Button; 9 10 public class MainActivity extends Activity { 11 12 private Button button; 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 19 button = (Button) findViewById(R.id.button); 20 Log.e("Test", "getWidth寬度:" + button.getWidth()); 21 Log.e("Test", "getHeight高度:" + button.getMeasuredWidth()); 22 23 new Thread() { 24 25 @Override 26 public void run() { 27 synchronized (this) { 28 try { 29 wait(1000);// 1秒 30 } catch (InterruptedException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 } 35 36 Log.e("Test", "高度:" + button.getHeight()); 37 Log.e("Test", "寬度:" + button.getWidth()); 38 39 Log.e("Test", "左上角坐標x:" + button.getLeft()); 40 Log.e("Test", "左上角坐標y:" + button.getTop()); 41 42 Log.e("Test", "右下角坐標x:" + button.getRight()); 43 Log.e("Test", "右下角坐標y:" + button.getBottom()); 44 45 } 46 }.start(); 47 48 } 49 50 }
運行程序如下:
(2)自己使用API測量:
1 package com.himi.test; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.View; 7 import android.widget.Button; 8 9 public class MainActivity extends Activity { 10 11 private Button button; 12 13 @Override 14 protected void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.activity_main); 17 18 button = (Button) findViewById(R.id.button); 19 20 21 22 int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 23 int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 24 button.measure(w, h); 25 26 int height = button.getMeasuredHeight(); 27 int width = button.getMeasuredWidth(); 28 29 Log.e("Test", "寬度:" + width); 30 Log.e("Test", "高度:" + height); 31 32 Log.e("Test", "左上角坐標x:" + button.getLeft()); 33 Log.e("Test", "左上角坐標x:" + button.getTop()); 34 35 Log.e("Test", "左上角坐標x:" + button.getRight()); 36 Log.e("Test", "左上角坐標x:" + button.getBottom()); 37 38 39 40 41 } 42 43 }
運行程序如下:
(3)我們需要注冊一個ViewTreeObserver的監聽回調,這個監聽回調OnGlobalLayoutListener,就是全局的布局改變監聽器,所以是最推薦使用的:
ViewTreeObserver:這是一個注冊監聽視圖樹的觀察者(observer),在視圖樹種全局事件改變時得到通知。這個全局事件不僅還包括整個樹的布局,從繪畫過程開始,觸摸模式的改變等。ViewTreeObserver不能夠被應用程序實例化,因為它是由視圖提供,參照getViewTreeObserver()以查看更多信息。
1 package com.himi.test; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.ViewTreeObserver; 7 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 8 import android.widget.Button; 9 10 public class MainActivity extends Activity { 11 12 private Button button; 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 19 button = (Button) findViewById(R.id.button); 20 21 22 final ViewTreeObserver vto = button.getViewTreeObserver(); 23 vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 24 @Override 25 public void onGlobalLayout() { 26 button.getViewTreeObserver().removeGlobalOnLayoutListener(this); 27 int height = button.getMeasuredHeight(); 28 int width = button.getMeasuredWidth(); 29 30 31 Log.e("Test", "高度:" + height); 32 Log.e("Test", "寬度:" + width); 33 34 35 36 37 Log.e("Test", "左上角坐標x:" + button.getLeft()); 38 Log.e("Test", "左上角坐標y:" + button.getTop()); 39 40 Log.e("Test", "右下角坐標x:" + button.getRight()); 41 Log.e("Test", "右下角坐標y:" + button.getBottom()); 42 43 } 44 }); 45 } 46 47 }
部署程序到手機上,如下: