转自: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.
大概意思:
当前窗体得到或失去焦点的时候的时候调用。这是这个活动是否是用户可见的最好的指标。默认的实现清除重点跟踪状态,所以应该总是被调用。请注意,这提供了有关整体焦点状态信息,这是独立管理活动的生命周期。因此,焦点的变化通常会有一些关系生命周期变化(一种活动停止一般不会得到窗口焦点),你应该不依赖于任何特定的顺序之间的回调在这里和那些在其他生命周期方法如onresume()。作为一般规则,然而,一个恢复活动将得到窗口焦点…除非有其他对话框弹出窗口显示或接受输入焦点,在这种情况下,活动本身不会有焦点时,其他窗口拥有它。同样,系统会显示系统顶层窗口(如状态栏通知面板或警报系统)将暂时不停顿的前台活动带窗口的输入焦点。
在Activity的生命周期中,onCreate()--onStart()--onResume()都不是窗体Visible的时间点,真正的窗体完成初始化可见获取焦点可交互是在onWindowFocusChanged()方法被执行时,而这之前,对用户的操作需要做一点限制。比如我们在做OTT项目时候,我们就是在这onWindowFocusChanged来获取主按键的具体位置和宽高的,而在其他标准生命周期的接口中调用都是获取不到的,比如在onResume,onStart中都获取不到信息。这个onWindowFocusChanged指的是这个Activity得到或者失去焦点的时候 就会call。。也就是说 如果你想要做一个Activity一加载完毕,就触发什么的话 完全可以用这个!!!使用一个view的getWidth() getHeight() 方法来获取该view的宽和高,返回的值却为0。如果这个view的长宽很确定不为0的话,那很可能是你过早的调用这些方法,也就是说在这个view被加入到rootview之前你就调用了这些方法,返回的值自然为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");
}
}
跳转的页面:
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:
在窗体不能交互的时候,弹出对话框之类有可能会报错,在初始化过程中,讲与其他窗口有关的操作放到获取到焦点后操作。
/**
* bug :unable to add window -- token null is not
* 添加窗体在视图初始化完成过后
*
* @param hasFocus
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
//add Window.....
}
}