我抓住了The Busy Coder's Guide to Android Development 4.2中演示的EU4You 示例项目(由 StackOverflow 上的 Mark Murphy aka commonsware提供)。跟随这个示例项目可能更容易,但我会尝试在问题中发布相关的代码部分。您还需要导入ActionBarSherlock项目。您还需要将 Java 编译器设置为 1.6(以允许使用 @Override 注释)。
注意:我已将 min-sdk 更改为 8(2.3,Froyo),将 target-sdk 更改为 16(4.1,Ice Cream Sandwich)。
注意:我已将countries
framelayout id更改为left_pane
并将framelayout id 更改details
为right_pane
.
主布局文件(layout-large-land):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/left_pane"
android:layout_weight="30"
android:layout_width="0px"
android:layout_height="fill_parent"
/>
<FrameLayout
android:id="@+id/right_pane"
android:layout_weight="70"
android:layout_width="0px"
android:layout_height="fill_parent"
/>
</LinearLayout>
主要布局文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/left_pane"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
示例应用程序的原始版本有两个活动(确切地说是 SherlockFragmentActivities)。
- EU4You - 加载适当的布局(默认或横向大)。如果默认,则在 SherlockListFragment 中加载国家列表。如果横向大,加载列表和详细信息片段以显示所选国家。
- DetailsActivity - 在不使用横向大布局时通过 DetailsFragment 加载所选国家。
如果您单击列表片段中的国家/地区,EU4You(主要托管活动)会检查 DetailsFragment 的存在和可见性。如果存在,它会在该片段中加载国家网站。如果没有,它会触发 DetailsActivity,然后处理添加 DetailsFragment(然后加载给定国家/地区的网站)。
这很好用,就像在平板电脑和手机上支持多种屏幕布局的典型应用程序一样。
我的问题是我想删除 DetailsActivity 并坚持一个活动。每当我不在大横向布局中时(换句话说,我在平板电脑上的纵向布局或任何方向的手机上),我都想用详细信息片段交换(替换)列表片段。所以我所做的是在 EU4You SherlockFragmentActivity 中更改了以下内容:
原始(对注释中提到的框架布局名称进行了轻微的命名修改......国家是left_pane,细节是right_pane):
@Override
public void onCountrySelected(Country c) {
String url=getString(c.url);
if (details != null && details.isVisible()) {
details.loadUrl(url);
}
else {
Intent i=new Intent(this, DetailsActivity.class);
i.putExtra(DetailsActivity.EXTRA_URL, url);
startActivity(i);
}
}
我修改后的单一活动版本:
@Override
public void onCountrySelected(Country c) {
String url=getString(c.url);
if (details != null && details.isVisible()) {
details.loadUrl(url);
}
else {
details = new DetailsFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.left_pane, details);
ft.addToBackStack(null);
ft.commit();
getSupportFragmentManager().executePendingTransactions();
details.loadUrl(url);
}
}
这按预期工作。我单击列表中的网站(在平板电脑上以纵向模式,或在任何方向的手机上),详细信息显示在详细信息片段中,它替换了网站列表片段。但是,如果我在显示国家/地区详细信息时单击设备上的主页按钮,我会收到强制关闭错误,并显示以下 logcat 详细信息(仅使用默认布局,只有一个 left_pane 框架布局......我没有当存在 left_pane 和 right_pane 时,平板电脑上的横向方向存在此问题):
11-16 15:04:33.525: E/AndroidRuntime(688): FATAL EXCEPTION: main
11-16 15:04:33.525: E/AndroidRuntime(688): java.lang.RuntimeException: Unable to pause activity {com.commonsware.android.eu4you/com.commonsware.android.eu4you.EU4You}: java.lang.IllegalStateException: Content view not yet created
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3348)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3305)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3288)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.access$2500(ActivityThread.java:125)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2040)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.os.Handler.dispatchMessage(Handler.java:99)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.os.Looper.loop(Looper.java:123)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.main(ActivityThread.java:4627)
11-16 15:04:33.525: E/AndroidRuntime(688): at java.lang.reflect.Method.invokeNative(Native Method)
11-16 15:04:33.525: E/AndroidRuntime(688): at java.lang.reflect.Method.invoke(Method.java:521)
11-16 15:04:33.525: E/AndroidRuntime(688): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-16 15:04:33.525: E/AndroidRuntime(688): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-16 15:04:33.525: E/AndroidRuntime(688): at dalvik.system.NativeStart.main(Native Method)
11-16 15:04:33.525: E/AndroidRuntime(688): Caused by: java.lang.IllegalStateException: Content view not yet created
11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
11-16 15:04:33.525: E/AndroidRuntime(688): at com.commonsware.android.eu4you.CountriesFragment.onSaveInstanceState(CountriesFragment.java:64)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1574)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1644)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:499)
11-16 15:04:33.525: E/AndroidRuntime(688): at com.actionbarsherlock.app.SherlockFragmentActivity.onSaveInstanceState(SherlockFragmentActivity.java:127)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.Activity.performSaveInstanceState(Activity.java:1036)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1180)
11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3330)
11-16 15:04:33.525: E/AndroidRuntime(688): ... 12 more
如果我从上面的代码中删除以下行,我可以阻止此错误的发生:
ft.addToBackStack(null);
我确实需要能够将替换事务添加到后台堆栈,所以我不能删除这一行(这个示例应用程序是我真正的应用程序的基础,它有更多的东西,但我用它来简化我的问题)。
所以两个问题:
- 为什么会这样?
- 我该如何解决它(也许是另一种方法)?
需要注意的一点是,在我的实际应用程序中,此逻辑必须全部位于操作栏中的选项卡内(ActionBarSherlock,因为我必须支持回到版本 2.3 (Froyo))。
更新(2012 年 11 月 22 日 13:27 EST)
我在GitHub 上发布了一个示例项目。我是 Eclipse 和 Android 开发的新手,所以我可能没有包含我需要的所有东西(工作空间不包括在内,我认为 ActionBarSherlock 项目不包括在内......它需要导入(可以在这里找到) )。