【发布时间】:2015-07-23 12:32:01
【问题描述】:
这是实际问题的缩小版本。重现我面临的困难。
我以官网developer.android.com的例子来引用我的问题。
Building a Flexible UI
MainActivity 有 2 个布局。一种是layout 文件夹中的默认(小屏幕设备中的纵向)布局。大屏幕和横向模式的另一种布局,保存在layout-large 和layout-land 文件夹中。
activity_main.xml 的默认布局仅包含一个 FrameLayout (R.id.fragment_container),我在其中动态添加和替换我创建的 2 个片段。
layout-land 和 layout-large 文件夹的其他布局相同。它有 2 个静态片段 [R.id.headlines_fragment - 显示标题列表] 和 [R.id.article_fragment - 选择标题时显示详细信息]。水平放置。左侧显示列表,右侧显示详细信息。
这是控制所有片段的MainActivity.java 的代码:
public class MainActivity extends Activity implements OnHeadLineSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_article);
if(findViewById(R.id.fragment_container) != null) {
if(savedInstanceState != null) {
return;
}
HeadlinesFragment firstFragment = new HeadlinesFragment();
firstFragment.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(R.id.fragment_container, firstFragment).commit();
}
}
@Override
public void onArticleSelected(int position) {
ArticleFragment articleFrag = (ArticleFragment) getFragmentManager().findFragmentById(R.id.article_fragment);
if(articleFrag != null && articleFrag.isVisible()) {
articleFrag.updateArticleView(position);
} else {
articleFrag = new ArticleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction().replace(R.id.fragment_container, articleFrag);
transaction.addToBackStack(null);
transaction.commit();
}
}
}
活动一开始,我就检查fragment_container 即FrameLayout 是否存在。如果它不存在,则具有 2 个片段的布局已加载。因此无需动态添加片段,因为它们已经存在。
否则,我检查savedInstanceState 是否为空。如果为 null,则创建一个新的 HeadlinesFragment 并将其添加到框架中。如果它不为空,则表示之前已经创建了活动,因此必须已经添加了HeadlinesFragment。无需再次添加。所以,return。
并且onArticleSelected() 方法用ArticleFragment 替换框架中的现有片段,或者如果在其他布局中,它只是更新已经存在的片段。 It is called from the HeadlinesFragment when an item is selected.
现在,如果我们以纵向模式进入活动,然后更改方向,这一切都可以正常工作。没问题。完美无瑕。
但是如果我们以landscape模式进入activity,一旦我将方向更改为纵向模式,就会显示一个空白屏幕。
原因是,onCreate() 被调用,而savedInstanceState 返回的不是null。因此,HeadlinesFragment 不会被创建并添加到框架中。
是的,如果我删除该检查,那么应用程序可以正常工作,但这意味着每次都会创建一个新的HeadlinesFragment 并将其添加到框架中,并堆叠在彼此之上。这一点也不可取。
我无法通过找出orientation 并应用适当的布局来实现这一点。因为,在大屏设备中,即使是纵向模式,也应该同时显示两个片段。
我尝试了许多复杂的逻辑。但似乎没有任何效果。任何帮助表示赞赏。
以纵向模式输入活动
1> 显示列表项。
2> 单击项目会将片段替换为 ArticleFragment(详细信息)。
3> 改变方向,并排显示。一切正常。
以横向模式进入活动
1> 显示列表和详细信息。一切正常。
2> 但是一旦方向改变,你就会得到空白屏幕。由于没有创建和添加标题片段。
如果有人能指导我如何解决这个问题,那将非常有帮助。而且由于实际项目很大,而且这个逻辑已经实现,逻辑上的剧烈变化不再是一种选择,因为这意味着要重新编写数千行代码。谢谢你。 :)
【问题讨论】:
-
您可以使用 .replace mtehod 而不是 .add 以避免将片段堆叠在一起。这并不能解决每次都会创建一个新片段的事实
-
当然我已经想到了,但是第一次创建活动呢?框架中没有任何东西可以替换。我确实试过了。它抛出一个异常。所以,不是一个选择。 :(
-
真的会抛出异常吗?我很少使用 add 方法,因为它更方便,而且我没有遇到过这个问题。你得到什么例外?
-
第一次你必须在框架布局中添加一些东西,然后只有你可以从下一次开始替换它。但这确实给了我一个想法。如果我在 xml 文件本身中静态放入一个随机片段会怎样。然后我可以每次都调用replace。我会试试看。
标签: java android android-layout android-fragments landscape-portrait