【问题标题】:layout with fragment and framelayout replaced by another fragment and framelayout带有片段和框架布局的布局被另一个片段和框架布局替换
【发布时间】:2011-07-20 19:55:13
【问题描述】:

编辑:

所以在下面的 cmets 之后,我重新审视并意识到是什么让我陷入困境。

想象一下我的客户列表和客户详细信息活动由以下人员开始:

public class ClientsMainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //StudioTabOpenHelper db;
        setContentView(R.layout.main_client_activity);
    }
}

所以这很好用,启动我的 main_client_Activity(在下面的布局中定义,当我点击主屏幕上的按钮时我调用这个活动):

Intent intent = new Intent(getActivity(), ClientsMainActivity.class);
startActivity(intent);

问题很简单,ClientsMainActivity 不调用 OnCreateView 或任何东西,只是将布局设置为定义我的 Fragment 和我的 ListFragment 的布局。这很好,因为我不想将任何东西传递给ClientsMainActivity,但如果我有一个假设的活动,比如:

SessionMainsActivity 当他们单击客户端的会话编辑时调用,然后我不会以相同的方式调用SessionsMainActivity(启动仅设置为布局的活动),我希望该布局设置为它定义了我的片段是如何拆分的。但我也想将数据传递给它,然后传递给后续的片段(比如他们点击哪个会话进行编辑/处理。

所以我想知道以上是否有道理,我确信这是一件简单的事情,我无法将我的大脑包裹起来。我从其他片段调用FragmentActivities 没有问题,它们占据了整个屏幕,但它可以工作。所以我想最大的问题是ClientsMainActivity 来自我在网上找到的一些示例,用于制作向您展示如何在屏幕上制作多个片段的食谱。让我得到FragmentActivity 所做的所有事情就是将内容视图设置为一个可以完成所有工作的布局,所以这就是为什么我不知道如何编写代码来做同样的事情,但让我通过布局定义的片段的值等等......

结束编辑

所以我在这里使用这个不错的小教程:

http://developer.android.com/guide/topics/fundamentals/fragments.html

它让我走了很长一段路,并利用他们所说的主要活动和 fragment_layout.xml,我在左边有一个很好的客户列表(那是一个 listfragment),在右边有一个细节片段。

然后我添加了在客户端上编辑会话信息(或编辑客户端详细信息)的功能,这两者都是全屏片段。这效果很好。

现在我决定我的会话编辑 ui 最好再次将信息分成两个窗格。

这不像我想的那样工作,就像我说我有一个在 onCreate 中执行此操作的 main_Activity:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_client_activity);
}

main_client_activity.xml 在两种布局中定义,但用于横向平板电脑的布局在这里:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <fragment class="com.viciousbytes.studiotab.subactivities.ClientListView"
        android:id="@+id/client_list" android:layout_weight="1"
        android:layout_width="0px" android:layout_height="match_parent" />

   <FrameLayout android:id="@+id/client_details" android:layout_weight="1"
        android:layout_width="0px" android:layout_height="match_parent"
        android:background="?android:attr/detailsElementBackground"/>

</LinearLayout>

这一切都很好!在这种情况下,我将其他所有内容作为开始其自己的片段的全屏活动来处理:

EditSessionActivity EditClientActiivyt 两者都使用 getSupportFragmentManager().beginTransaction ,我可以从 .newInstance 调用中将信息传递给它。

我的session_edit.xml 布局用按钮、文本视图等定义......效果很好。这就是我在我的EditSessionActivity“启动”的SessionEdit 片段中加载的内容,但现在因为我想把它分开,我遇到了一个障碍。上面我定义了一个 client_list 和一个 client_details id,这些占位符在我的屏幕上吗?当我想用完全不同的片段替换那里的东西时,我应该引用那些吗?

或者我是否构建另一个名为 fragment_session_layout 的片段布局,它定义了如下内容:

<?xml version="1.0" encoding="utf-8"?>    
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

   <fragment class="com.viciousbytes.studiotab.subactivities.SessionEdit"
        android:id="@+id/session_edit" android:layout_weight="1"
        android:layout_width="0px" android:layout_height="match_parent" />

   <FrameLayout android:id="@+id/invoice_details" android:layout_weight="1"
        android:layout_width="0px" android:layout_height="match_parent"
        android:background="?android:attr/detailsElementBackground" />
</LinearLayout>

抱歉,我的舌尖上不知道该取什么标题,基本上是如何将两个片段窗格重复一遍。在线演示展示了如何做一个(以及一个简单的 ListFragment)。

我已经完成了上述所有操作,但我无法弄清楚如何将我需要的数据传递到片段中,我在 EditSessionActivity 中使用了它:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    int clientID = getIntent().getIntExtra(THE_SELECTED_CLIENT, -1);            
    int sessionID = getIntent().getIntExtra(SELECTED_SESSION,-1);
    SessionEdit edits = SessionEdit.newInstance(this.getBaseContext(), false, clientID, sessionID);
    mUIListener = (OnUpdateUI)edits;
    getSupportFragmentManager().beginTransaction().add(android.R.id.content, edits).commit();
}

这行得通,但是为了尝试遵循前面的片段示例,我假设我的EditSessionActivity 有点像制作另一个MainActivity(因为它像主面板一样有两个面板)。所以我用这个重新编码了EditSessionActivity中的onCreate

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

在处理 onCreateView 的 EditSession 片段中进行斗争之后,我终于让它工作了,但无法传递数据,因为没有像之前的 onCreate 那样使用具有 edits=SessionEdit.newInstance(...) 的对象的实例化

那么,做另一个有两个痛点的片段布局并在触发正确的操作时启动它是一种好习惯吗?还是应该替换两个已经创建的片段?不知何故来自我的main_client_activity.xml

【问题讨论】:

  • 我现在有同样的“问题”,我在视图中有 2 个列表片段,并且在选择一行后我正在动态更改。我认为很多哪个更好,但我不认为这是我用过的最好的方法。
  • 网上的这些片段的例子对于简单的案例来说通常已经足够了,但除此之外,你就得靠你自己了。希望有人有好的建议。
  • 我同意你的看法,本教程适用于基本情况,如果有人想用片段创建复杂的 UI,他需要多想:D
  • 我不介意想我只是想知道做事的正确方法,以便将来不创建纸牌屋软件 :) 我现在甚至正在与我创建的 DialogFragment 搏斗使用他们的教程,它可以工作,但作为自己的 UI“页面”出现,而不是作为“悬停”在其他内容之上的对话框,不确定我做错了什么。我的日期/时间对话框片段虽然 Shrug 工作得很好

标签: android android-fragments


【解决方案1】:

我假设编辑客户端和编辑会话是两个不同的活动。当您从“编辑客户端”切换到“编辑会话”模式时,“列表”和“详细信息”窗格都会改变吗?

我会使用两个布局文件,而不是尝试重用相同的布局并在其中重新加载片段。

如果您尝试重复使用相同的布局,您必须:

  • @+id/invoice_details 更改为@+id/right_pane。否则,将与会话相关的内容加载到“invoice_details”占位符中会让人感到困惑。
  • 用另一个FrameLayout 替换片段定义并在运行时加载ClientListViewSessionListView(或者无论如何它被称为)片段。

在我看来,这将比拥有另一个布局 xml 文件增加更多的复杂性。

所以

  • 使用您现有的与客户列表和客户详细信息一起使用的代码
  • 复制所有涉及的部分,并更改需要更改的部分,因此现在是会话列表和会话详细信息
  • 在容易做到的地方删除重复项(常用函数到实用程序类,常用布局元素到布局包括)。将难以重复数据删除的内容保留原样。
  • 稍后再评估,当您有更多片段、更多布局和更多经验时。

更新,关于片段可以嵌入到活动中的两种不同方法

正如 Android 文档所述,您可以通过两种主要方式让片段显示在 Activity 中:

  • 在布局的 XML 文件中声明片段 (&lt;fragment class=.... /&gt;)
  • 在布局的 XML 文件中放置一个占位符 FrameLayout 并在运行时加载片段

当片段不需要接收任何参数时,第一种方法很好。例如,如果检索单个且唯一的客户端列表的逻辑被硬编码在片段的代码中。

第二种方法允许您将参数传递给片段,因此适用于“详细信息深入分析”类型的片段。

从更新的问题我了解到,

  • 每个客户端都有一个单独的会话列表
  • 正在使用的组件是:EditSessionActivity,它承载两个片段,一个用于显示会话列表,另一个用于显示会话详细信息

如果这是正确的,那么您确实需要以编程方式加载这两个片段,因为两者都需要传递参数。所以你的布局会有两个FrameLayouts。 EditSessionActivity 将首先从意图中获取一些参数(“我们正在使用哪个会话列表?”),并使用这些参数加载“会话列表”片段。当用户选择该片段中的列表项时,另一个片段将加载会话详细信息。

【讨论】:

  • 感谢您的回复。我要解决这个问题。我认为最大的问题是我的布局代码的工作方式是一侧是 ListFragment,另一侧只是 FrameLayout。因此,在我的会话内容中,我想要两个 FrameLayouts(或者此时它们会是片段?)我想我也对在这种情况下如何将一些复杂对象(我自己的数据对象)传递给 FragmentActivity 感到困惑,也许只是使其可序列化?我有一段时间没看这个了,所以我会仔细检查一下是哪一部分特别挂了我,然后在这里重新发布。
  • 如果会话内容类似于客户端(左侧的会话列表,右侧的会话详细信息),那么我认为您的布局也将类似:左侧为 ListFragment,右侧为 FrameLayout。当在左侧列表中选择一个项目时,一个用于编辑会话详细信息的片段将被加载到 FrameLayout 中。至于传递数据:可序列化(可打包)对象或全局状态。或者,如果对象来自本地 sqlite 数据库之类的东西,您可以传递数据库 ID,并在需要时从数据库中读取对象。
  • 更新了我的答案,希望它能解决您的问题。
  • 所以我的 EditSessionActivity 将加载定义了两个框架布局的框架布局内容视图(并且我以编程方式)构建片段,那是在另一个片段活动中还是在 EditSessionActivity 中我会构建并加载两个片段?
  • 是的,我很困惑我猜如何加载两个框架布局?并从主要的EditSessionActivity FragmentActivity 加载所有片段。
最近更新 更多