標籤:main 簡單 rri ever onpause super 直接 lis code
今天來簡單的介紹一下怎麼在Activity中拿到View的width和height。有人可能會疑問,這個有什麼難的,我們直接可以在Activity生命週期函數裡面擷取width和height。看似簡單,實際上在onCreate、onStart、onResume中均無法擷取正確的width和height,這是因為View的measure過程和Activity的生命週期方法不是同步的,因此無法保證Activity執行了onCreate、onStart、onResume時,某個View已經測量完畢,如果View還沒有測量完畢的話,那麼獲得的寬和高就是0.那麼有什麼方法來正確的擷取呢?
1.onWindowFoucusChanged
1 public class MainActivity extends AppCompatActivity { 2 3 private Button mButton = null; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 mButton = (Button) findViewById(R.id.id_button);11 12 }13 14 @Override15 public void onWindowFocusChanged(boolean hasFocus) {16 super.onWindowFocusChanged(hasFocus);17 if (hasFocus) {18 int width = mButton.getMeasuredWidth();19 int height = mButton.getMeasuredHeight();20 Log.i("main", "width = " + width + " height = " + height);21 }22 }23 }
onWindowFocusChanged這個方法的定義是:View已經初始化完畢了,width和height已經準備好了,這個時候去擷取width和height是沒有問題的。需要注意的是:onWindowFocusChanged會調用多次,當Activity的視窗得到焦點和失去焦點時均會被調用一次。具體來說,當Activity繼續執行和暫停執行時,onWindowFocusChanged均會被調用,如果頻繁的進行onResume和onPause,那麼onWindowFocusChanged也會被頻繁的調用。
2.view.post(Runnable)
1 public class MainActivity extends AppCompatActivity { 2 3 private Button mButton = null; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 mButton = (Button) findViewById(R.id.id_button);11 mButton.post(new Runnable() {12 @Override13 public void run() {14 int width = mButton.getMeasuredWidth();15 int height = mButton.getMeasuredHeight();16 Log.i("main", "width = " + width + " height = " + height);17 }18 });19 }20 21 }
我們可以通過post方法將一個runnable對象投遞到mButton的訊息佇列的尾部,然後等待Looper調用此runnable的時候,View已經初始化好了。
3.ViewTreeObserver
1 public class MainActivity extends AppCompatActivity { 2 3 private Button mButton = null; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 10 mButton = (Button) findViewById(R.id.id_button);11 }12 13 @Override14 protected void onStart() {15 super.onStart();16 ViewTreeObserver viewTreeObserver = mButton.getViewTreeObserver();17 viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {18 @Override19 public void onGlobalLayout() {20 mButton.getViewTreeObserver().removeOnGlobalLayoutListener(this);21 int width = mButton.getMeasuredWidth();22 int height = mButton.getMeasuredHeight();23 }24 });25 }26 }
使用ViewTreeObsrever的眾多回調可以完成這個功能,比如使用OnGlobalLayoutListener這個介面,當View樹的狀態發生改變或者View內部的View的可見度發生改變時,onGlobalLayout方法將被回調,因此這是擷取View的width和height一個很好的時機。需要注意的是,伴隨著View樹的狀態改變等等,onGlobalLayout會被調用多次。
Android擴充-怎麼在Activity中拿到一個View的寬和高