轉(zhuǎn)自:http://blog.csdn.net/yueqinglkong/article/details/44981449
看看源碼中對該方法的說明:
Called when the current Android.view.Window
of the activity gains or loses focus. This is the best indicator of whether this activity is visible to the user. The default implementation clears the key tracking state, so should always be called.
Note that this provides information about global focus state, which is managed independently of activity lifecycles. As such, while focus changes will generally have some relation to lifecycle changes (an activity that is stopped will not generally get window focus), you should not rely on any particular order between the callbacks here and those in the other lifecycle methods such asonResume()
.
As a general rule, however, a resumed activity will have window focus... unless it has displayed other dialogs or popups that take input focus, in which case the activity itself will not have focus when the other windows have it. Likewise, the system may display system-level windows (such as the status bar notification panel or a system alert) which will temporarily take window input focus without pausing the foreground activity.
大概意思:
當前窗體得到或失去焦點的時候的時候調(diào)用雨效。這是這個活動是否是用戶可見的最好的指標蛤高。默認的實現(xiàn)清除重點跟蹤狀態(tài)撵彻,所以應該總是被調(diào)用艺演。請注意,這提供了有關(guān)整體焦點狀態(tài)信息贱傀,這是獨立管理活動的生命周期惨撇。因此,焦點的變化通常會有一些關(guān)系生命周期變化(一種活動停止一般不會得到窗口焦點)府寒,你應該不依賴于任何特定的順序之間的回調(diào)在這里和那些在其他生命周期方法如onresume()魁衙。作為一般規(guī)則,然而椰棘,一個恢復活動將得到窗口焦點…除非有其他對話框彈出窗口顯示或接受輸入焦點纺棺,在這種情況下榄笙,活動本身不會有焦點時邪狞,其他窗口擁有它。同樣茅撞,系統(tǒng)會顯示系統(tǒng)頂層窗口(如狀態(tài)欄通知面板或警報系統(tǒng))將暫時不停頓的前臺活動帶窗口的輸入焦點帆卓。
在Activity的生命周期中巨朦,onCreate()--onStart()--onResume()都不是窗體Visible的時間點,真正的窗體完成初始化可見獲取焦點可交互是在onWindowFocusChanged()方法被執(zhí)行時剑令,而這之前糊啡,對用戶的操作需要做一點限制。比如我們在做OTT項目時候,我們就是在這onWindowFocusChanged來獲取主按鍵的具體位置和寬高的,而在其他標準生命周期的接口中調(diào)用都是獲取不到的吁津,比如在onResume棚蓄,onStart中都獲取不到信息。這個onWindowFocusChanged指的是這個Activity得到或者失去焦點的時候 就會call碍脏。梭依。也就是說 如果你想要做一個Activity一加載完畢,就觸發(fā)什么的話 完全可以用這個5湮病R鬯!使用一個view的getWidth() getHeight() 方法來獲取該view的寬和高钾埂,返回的值卻為0河闰。如果這個view的長寬很確定不為0的話,那很可能是你過早的調(diào)用這些方法褥紫,也就是說在這個view被加入到rootview之前你就調(diào)用了這些方法姜性,返回的值自然為0.
下面測試代碼:
public class MainActivity extends Activity {
private String Tag = "MainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
Log.d(Tag, "onCreate");
}
public void init() {
Button nextBtn = (Button) findViewById(R.id.btn_next);
nextBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, NextActivity.class);
startActivity(intent);
}
});
Button nextBackBtn = (Button) findViewById(R.id.btn_next_back);
nextBackBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, NextActivity.class);
startActivityForResult(intent, 10);
}
});
Button dialogBtn = (Button) findViewById(R.id.btn_dialog);
dialogBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("確認")
.setMessage("確定嗎?")
.setPositiveButton("是", null)
.setNegativeButton("否", null)
.show();
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(Tag, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(Tag, "onResume");
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
Log.d(Tag, "onAttachedToWindow");
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
Log.d(Tag, "onWindowFocusChanged:" + "true");
} else {
Log.d(Tag, "onWindowFocusChanged:" + "false");
}
}
@Override
protected void onPause() {
super.onPause();
Log.d(Tag, "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(Tag, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(Tag, "onDestroy");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(Tag, "onActivityResult");
}
}
跳轉(zhuǎn)的頁面:
public class NextActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
init();
}
public void init() {
Button backBtn = (Button) findViewById(R.id.btn_setback);
backBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setResult(15, null);
finish();
}
});
}
}
運行效果髓考,在圖中標注的很詳細了:
注意:
1.token null is not valid; is your activity running:
在窗體不能交互的時候污抬,彈出對話框之類有可能會報錯,在初始化過程中绳军,講與其他窗口有關(guān)的操作放到獲取到焦點后操作晌坤。
/**
* bug :unable to add window -- token null is not
* 添加窗體在視圖初始化完成過后
*
* @param hasFocus
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
//add Window.....
}
}