【问题标题】:Android - Change fragment layout in runtimeAndroid - 在运行时更改片段布局
【发布时间】:2011-10-23 09:53:27
【问题描述】:

我想在我的应用中实现单活动多片段设计。我计划有几个“屏幕”(片段的布局),我将在代码中切换(可能添加到后台堆栈)。

据我了解,每个屏幕中片段的布局是使用 Layout 对象(例如 FrameLayout)设置的,这些对象充当片段的占位符(共享相同的 ID)。由于不同的屏幕有不同的 Fragment 排列方式(一个可能是 FrameLayout,另一个是 LinearLayout 等)我想知道:如何在运行时在 Fragment 布局之间切换?

我了解添加/替换片段(通过 FragmentManager),但我想在实时活动中完全添加包含它们的新布局。有点像“setContentView”的交易......

我该怎么做? 谢谢!丹尼。

【问题讨论】:

  • 我在这里发布了单活动多片段代码:*.com/questions/7797389/…
  • 感谢您的快速回复。但是,我认为在您的示例中显示的相同布局中的片段之间切换(R.id.mainframe)并不能解决我的问题,即如何在片段布局之间切换。特别是如果布局是在代码中创建的(在调用 onContentView 之后),就像我的情况一样。
  • 哦,我明白了,所以您想重新父级现有片段而不重新实例化它们?这很有趣。
  • 对不起,如果我的解释很糟糕。 :) 我认为我的情况更简单。我想在新布局中创建新片段(这里没有重新设置)。据我了解,FragmentManager 不能定义新的布局,只能将片段连接到 Activity 布局中的现有占位符。由于我想创建新的布局,所以我遇到了问题。

标签: android android-layout android-fragments


【解决方案1】:

当然有可能,您唯一需要做的就是生成自己的 ID。 ID 可以是任何东西,但不能与 aapt ID(R 中的 ID)冲突,并且不能为负数。

以下示例使用一组固定 ID 演示了这一点:

public class MainActivity extends Activity {
    private final int ID_TABLE = 0xA;
    private final int ID_ROW1 = 0xB;
    private final int ID_ROW2 = 0xC;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        LinearLayout ll = (LinearLayout) findViewById(R.id.root);
        TableLayout tl = new TableLayout(this);
        tl.setId(ID_TABLE);
        TableRow tr1 = new TableRow(this);
        tr1.setId(ID_ROW1);
        TableRow tr2 = new TableRow(this);
        tr2.setId(ID_ROW2);
        tl.addView(tr1);
        tl.addView(tr2);
        ll.addView(tl);

        MyFragment frag1 = new MyFragment();
        MyFragment frag2 = new MyFragment();
        MyFragment frag3 = new MyFragment();
        MyFragment frag4 = new MyFragment();

        getFragmentManager().beginTransaction()
            .add(ID_ROW1, frag1, "cell1_1")
            .add(ID_ROW1, frag2, "cell1_2")
            .add(ID_ROW2, frag3, "cell2_1")
            .add(ID_ROW2, frag4, "cell2_2")
            .commit();
        getFragmentManager().executePendingTransactions();
    }
}

为了切换到不同的布局,您可以删除片段并将它们添加到其他地方。
告诉我进展如何。

编辑:澄清一下,Views 和 ViewGroups 不需要被实例化一次,然后在 Activity 的生命周期内保存。只需确保在删除相关视图之前删除或分离任何片段。此外,如果您在 onCreate 之外创建和删除视图,您应该确保它可以通过使用 onSaveInstanceState 并在 onCreate 中重复该过程来恢复。阅读diagram here 和关于configuration changes 的段落。

【讨论】:

  • 感谢您的努力!由于我是 Android 新手,我想确保我理解正确 - 可以在我的代码中的几乎任何地方,而不仅仅是在 onCreate(我不认为我见过这样的例子),然后动态地创建和添加片段?这不仅仅是“删除片段并将它们添加到其他地方”,因为我为它们创建了一个新布局。
  • 最终目标是将这个 Fragment 逻辑分离到不同的“屏幕”类中,并让每个类知道自己的布局 ID,并将自己的 Fragment 放入其中。然后我可以通过片段事务从一个“屏幕”导航到另一个“屏幕”。例如隐藏前一个屏幕的所有片段并显示新片段。我必须承认,这种技术看起来有点奇怪,因为它会使我的活动充满带有不可见片段的空布局......看起来我的目标是合理的,但我还没有找到正确的设计。
  • 嗯,这是一个有趣的思路,但这不正是活动及其 startActivity(Intent) 方法的用途吗?您也可以免费获得返回按钮功能。
  • 我对活动的问题是它们的整个存在都被框架过于“管理”了。我理解当你想向世界公开你的活动时的需要,但不是当它们在你的应用程序中时......无论如何,我需要我的“屏幕”类来动态生成他们自己的视图层次结构,所以我可以'每个屏幕都有一个活动类。相反,我需要创建一个屏幕实例,生成它的视图并按实例显示/隐藏它们,而不是按类。我也很可能想在不同的布局(平板电脑等)中重用我的“屏幕”,其中片段是理想的。
  • 资源管理器已经涵盖了针对不同设备使用不同的布局。 Please read this. 您可以拥有 layout-large-land、layout-large-port、layout-long-port-mdpi、layout-small-port-tvdpi 等。我正在开发一个基于不同布局的应用程序关于屏幕尺寸、纵向/横向和 api 级别(例如 layout-xlarge-land-v11)。只有很少的代码处理不同的配置。
【解决方案2】:
this.loadFragment(AlarmExample.newInstance())
this.loadFragment(XmlParsingFragment.newInstance())

private fun loadFragment(fragment: Fragment) {
    supportFragmentManager.beginTransaction()
        .replace(R.id.fragmentContainer, fragment)
        .commit()
}

通过这种方式,您可以根据需要设置任何片段。

【讨论】:

    最近更新 更多