以编程方式将多个片段添加到 RelativeLayout

Posted

技术标签:

【中文标题】以编程方式将多个片段添加到 RelativeLayout【英文标题】:Add multiple fragments programmatically to RelativeLayout 【发布时间】:2018-05-10 17:21:30 【问题描述】:

我想构建一个看起来像this 的视图,其中 Fragment2 的高度应该包裹它的内容,而 Fragment1 应该填充上面的剩余空间。

在阅读了执行此操作的方法后,我得到了该活动的以下 layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment_container"
    android:layout_
    android:layout_
    android:orientation="vertical"
    tools:context="com.jamest.textadventuretest.MainActivity">

    <fragment
        android:id="@+id/fragment1"
        android:name="com.jamest.textadventuretest.Fragment1"
        android:layout_
        android:layout_
        android:layout_above="@id/fragment2" />

    <fragment
        android:id="@+id/fragment2"
        android:name="com.jamest.textadventuretest.Fragment2"
        android:layout_
        android:layout_
        android:layout_alignParentBottom="true" />

</RelativeLayout>

它有效。 现在我想做同样的事情,但是以编程方式,这样我就可以用另一个片段(同时)替换/添加这两个片段。

我在 layout.xml 中注释掉了两个片段块,并将以下内容添加到我的活动的 onCreate() 方法中:

fragment2 = new Fragment2();
fragment1 = new Fragment1();

getSupportFragmentManager().beginTransaction()
    .add(R.id.fragment_container, fragment2)
    .add(R.id.fragment_container, fragment1).commit();

现在我必须设置 layout_above 和 layout_alignParentBottom 参数才能正确显示。

首先,我尝试在提交后通过调用 fragment1.getView() 将这些参数设置为视图,但我得到了 NullPointerException。 阅读后我明白,我只能在调用片段的 onCreateView() 方法后才能访问视图,而在调用 commit() 之后情况并非如此。就算后面跟着

getSupportFragmentManager().executePendingTransactions()

所以我在片段中创建了一个接口,在创建视图后调用方法(在 onActivityCreated() 中)并且活动实现了这些接口。

实现的方法如下所示:

@Override
public void onCreatedFragment1() 
    RelativeLayout.LayoutParams params =  new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
    params.addRule(RelativeLayout.ABOVE, R.layout.fragment2);
    fragment1.getView().setLayoutParams(params);

@Override
public void onCreatedFragment2() 
    RelativeLayout.LayoutParams params =  new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
    params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,1);
    fragment2.getView().setLayoutParams(params);

但是,我仍然只能看到 Fragment2 之上的 Fragment1... 如果我注释掉 Fragment1,我可以看到 Fragment2 在底部对齐。

解决这个问题的最佳方法是什么?

我想我可以在活动的 layout.xml 中添加两个单独的容器,但我想在应用程序中用更大的片段来回替换这两个片段。 那我应该把第二个容器空着吗? 还是有更好的办法?

提前致谢!

【问题讨论】:

我认为根据你的代码,你是先创建 fragment1 然后创建 fragment2,然后先创建 fragment2 然后再创建 fragment1(因为上述条件只适用于这种情况)。 以及为什么要将片段替换为相同的“R.id.fragment_container”,我认为您正在为两个片段替换相同的片段容器。 哦,那是一个错误(我将片段的名称更改为代码 sn-ps),我做到了!已编辑 【参考方案1】:

我不明白这一点,请检查此代码:

  getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, fragment2)
.add(R.id.fragment_container, fragment1).commit();

为什么要在同一个“fragment_container”上添加两个片段。

已编辑:

   RelativeLayout topLayout = (RelativeLayout)findViewById(R.id.content1);





    FrameLayout frameLayout2 = new FrameLayout(this);

    frameLayout2.setId(101);
    frameLayout2.setBackgroundColor(Color.BLUE);
    RelativeLayout.LayoutParams layoutParams= new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 200);
    layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
    frameLayout2.setLayoutParams(layoutParams);


    topLayout.addView(frameLayout2);




   FrameLayout frameLayout1 = new FrameLayout(this);
    frameLayout1.setBackgroundColor(Color.RED);

    layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

     layoutParams.addRule(RelativeLayout.ABOVE,frameLayout2.getId());
    frameLayout1.setLayoutParams(layoutParams);


    topLayout.addView(frameLayout1);

现在为 Fragments 编写代码:

     getSupportFragmentManager().beginTransaction()
    .add(frameLayout2, fragment2)
    .add(frameLayout1, fragment1).commit();

这里,topLayout 是父布局。 希望它对你有用。

【讨论】:

因为我只希望一个容器来容纳两个片段,所以它看起来像我给出的示例 xml。或者这不是做事的好方法? 您编辑的代码?我不知道你的意思......第一个片段不会替换第二个片段 - 如果我为第一个片段使用明确的高度,我可以看到它们! 嘿找到代码,我用正确的代码编辑了它。使用此代码肯定对您有用。 感谢您的代码。我想了很多,但我对使用这种方法犹豫不决,因为现在我必须跟踪并删除这两个 FrameLayout,如果我想用另一个片段切换这两个片段,而我只需要用更大的片段替换第一个片段一个并使用初始方法删除第二个。知道为什么我不像我试图做的那样工作吗?如果没有更多的答案,我会接受你的! 詹姆斯非常感谢您的赞赏,但对不起兄弟,我认为没有其他解决方案可以做到这一点。因为您总是需要两个框架布局来显示两个片段,并且您必须对其进行管理。抱歉,我了解您的情况。【参考方案2】:

好的,我终于得到了我想要达到的目标,虽然看起来有点麻烦。

我只是改变了

@Override
public void onCreatedFragment1() 
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
    params.addRule(RelativeLayout.ABOVE, R.layout.fragment2);
    fragment1.getView().setLayoutParams(params);

@Override
public void onCreatedFragment1() 
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
    params.addRule(RelativeLayout.ABOVE, fragment2.getView().getId();
    fragment1.getView().setLayoutParams(params);

我必须确保 fragment2 的视图是在 fragment1 之前创建的,否则我会得到 NullPointerException。

有没有更优雅的方式来实现我想要的,而无需事先在我的主要活动中定义多个 FrameLayouts?

【讨论】:

你为什么只想要一个容器?每个片段有 1 个容器是更好的做法。 只是因为大多数情况下只显示一个片段。替换其容器中的第一个片段并删除第二个片段,使其容器为空是否更好? 好的,我重读了你的问题,所以我现在明白你的意思了。我要做的是像你一样在相对布局中拥有两个 FrameLayout,然后将 RelativeLayout 嵌套在 FrameLayout 中。您可以用第三个 Fragment 或包含两个较小 Fragment 的 RelativeLayout 替换最外面的 FrameLayout 的内容。这有意义吗? 我想我明白了,就像this?但是我将如何通过 FragmentManager 切换回来?或者我会在内存中保留一份已填充的 RelativeLayout 吗?抱歉,如果这些是愚蠢的问题,这是我的第一个项目,我尝试通过指南推荐的片段来管理不同的“屏幕”。 您的图片看起来准确。至于将布局保留在内存中,这取决于您是否需要将其保留在内存中。是否需要从某个地方(如互联网服务器或其他东西)重新加载数据?他们是否需要记住用户的选择或偏好?在这些情况下,您可能希望保留碎片。最简单的方法就是更改相对布局的 z 位置。否则,如果所有数据都是静态的和/或快速加载的,您可以换出布局。

以上是关于以编程方式将多个片段添加到 RelativeLayout的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将按钮添加到片段

以编程方式将 GoogleMap 添加到片段

如何在没有 XML 的情况下以编程方式将片段添加到活动

以编程方式将片段添加到android中的框架布局

以编程方式替换片段

以编程方式将 Fragment 添加到 Kotlin 中的 Activity