最近写App里的设置界面时,参考 官方Guide 和 Android - Headers categories in PreferenceActivity with PreferenceFragment 将界面做好了,然后点击Header时,无论如何都没有弹出相应的Fragment。一番调查后发现,在Header被点击时,PerferenceActivity 的方法 onHeaderClick 的确被执行了:
public void onHeaderClick(Header header, int position) {
if (header.fragment != null) {
if (mSinglePane) {
int titleRes = header.breadCrumbTitleRes;
int shortTitleRes = header.breadCrumbShortTitleRes;
if (titleRes == 0) {
titleRes = header.titleRes;
shortTitleRes = 0;
}
startWithFragment(header.fragment, header.fragmentArguments, null, 0,
titleRes, shortTitleRes);
} else {
switchToHeader(header);
}
} else if (header.intent != null) {
startActivity(header.intent);
}
}
并且 startWithFragment 也被执行了:
public void startWithFragment(String fragmentName, Bundle args,
Fragment resultTo, int resultRequestCode, int titleRes, int shortTitleRes) {
Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleRes, shortTitleRes);
if (resultTo == null) {
startActivity(intent);
} else {
resultTo.startActivityForResult(intent, resultRequestCode);
}
}
onBuildStartFragmentIntent 也成功的创建了启动 Fragment 的 Intent:
public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
int titleRes, int shortTitleRes) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, getClass());
intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, titleRes);
intent.putExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, shortTitleRes);
intent.putExtra(EXTRA_NO_HEADERS, true);
return intent;
}
在自己实现的 PreferenceActivity 的子类 SettingActivity 的 onCreate 方法里加 trace,发现没有收到 onBuildStartFragmentIntent 创建的 intent。于是在 AndroidManifest.xml 里加上 intent filter:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
也没有作用。
Google了下资料,有看了看代码,发现 onBuildStartFragmentIntent 创建的 intent 是用于再创建一个 SettingActivity 实例,并将相应的 Fragment attach 上去,但 SettingActivity 在 AndroidManifest.xml 里设置了 singleTask 的 launch mode:
<activity
android:name="com.some.SettingActivity"
android:label="@string/action_settings"
android:launchMode="singleTask"
android:parentActivityName="com.some.MainMenuActivity"
android:theme="@style/AppTheme" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.some.MainMenuActivity" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
把 launchMode 的声明去掉后,Fragment 就成功启动了。因为 SettingActivity 会被创建多个实例,所以 parentActivityName 的声明也无用了。再去掉 intent filter,Fragment 还是能启动:
<activity
android:name="com.some.SettingActivity"
android:label="@string/action_settings"
android:theme="@style/AppTheme" >
</activity>