FragmentTransaction没有任何作用

13

我正在学习Fragment,并且以下是我的第一个Fragment程序。这是一个简单的项目,其中有两个屏幕。当我点击第一个屏幕的下一个按钮时,需要显示第二个按钮。

enter image description here

我针对Android 2.1及以上版本进行目标设置,使用兼容性包

AppMainFragmentActivity.java

public class AppMainFragmentActivity extends FragmentActivity {
  @Override
  protected void onCreate(Bundle arg0) {
    super.onCreate(arg0);
    setContentView(R.layout.app_main_layout);
  }
}

app_main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent" android:layout_height="fill_parent"
  android:orientation="vertical" android:id="@+id/fragment_container">

   <fragment class="com.research.fragmentstudy.FirstFragment"     
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" 
      android:id="@+id/id_first_fragment"/>

</LinearLayout>

FirstFragment.java

public class FirstFragment extends Fragment {
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.first_fragment_layout
                 , container,false);

     Button nextButton =(Button) view.findViewById(R.id.button);
     nextButton.setOnClickListener(nextListener);
     return view;
  }

  private OnClickListener nextListener  =   new OnClickListener() {
     @Override
     public void onClick(View v) {
        FragmentManager fm = ((AppMainFragmentActivity)FirstFragment.this
                           .getActivity()).getSupportFragmentManager();
        SecondFragment fragment = new SecondFragment();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.fragment_container, fragment);
        ft.commit();
     }
  };
}

首个碎片布局.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:orientation="vertical" android:id="@+id/first_fragment_root">

   <TextView android:layout_height="wrap_content" 
       android:layout_width="fill_parent"
       android:text="Fragment 1" android:gravity="center_horizontal" />

   <Button android:layout_height="wrap_content" 
       android:layout_gravity="center_horizontal"
       android:layout_width="wrap_content" android:id="@+id/button"
       android:text="Next" />

</LinearLayout>

SecondFragment.java

public class SecondFragment extends Fragment {
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
      View view = inflater.inflate(R.layout.second_fragment_layout,
                     container,false);
      return view;
   }
}

second_fragment_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:orientation="vertical" android:id="@+id/first_fragment_root">

   <TextView android:layout_height="wrap_content" 
      android:layout_width="fill_parent"
      android:text="Fragment 2" android:gravity="center_horizontal" />

</LinearLayout>

我成功地显示了第一个屏幕。现在,

我的理解是,期望发生的事情

  • 当我在第一个屏幕中点击下一步按钮时,SecondFragment 将被创建,它的 onCreate()onCreateView() 方法将被调用。
  • SecondFragment 将被显示,并且 FirstFragment 将被销毁(因为我没有将其添加到返回栈中)。由于默认的片段事务不具有动画效果,所以不会有任何动画效果。

实际上发生的事情

  • SecondFragment 被成功创建,其 onCreate()onCreateView() 方法得到了调用。
  • 但是 FirstFragment 仍然停留在屏幕上,而第二个片段从未显示。

现在,我的 Fragment 的理解可能是错误的。但是,我认为当我们提交一个 Fragment 事务时,第一个 Fragment 应该被替换为第二个 Fragment(第一个 Fragment 要么被隐藏或销毁)。可是好像什么都没有发生。这是为什么呢?我们需要手动销毁/隐藏第一个 Fragment 吗?

注意:我知道这对于如此基本的问题来说是一个很长的问题。但我放上了我的整个代码,因为我不确定我哪里搞错了。

3个回答

17

好的,我已经搞定了。这个问题的两个答案都正确地指出了我的代码不能按预期工作的一个原因。但是我的代码中有两个错误。

使用 fragmentTransaction.add() 不会显示新片段在旧片段上方。你需要调用 replace() 方法。给出的答案是正确的。

但是我的代码中还有一个错误。你不能替换在 xml 中静态创建的片段。所以我改变了

app_main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent" android:layout_height="fill_parent"
  android:orientation="vertical" android:id="@+id/fragment_container">

</LinearLayout>

AppMainFragmentActivity.java

并且

public class AppMainFragmentActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        setContentView(R.layout.app_main_layout);

        FragmentManager fragmentManager = getSupportFragmentManager();
        FirstFragment fragment = new FirstFragment();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container,fragment);
        fragmentTransaction.commit();           
    }
}

这是一个陷阱!因为有很多名为add()的函数...但只有fragmentTransaction.add(R.id.fragment_container,fragment); 起作用...浪费时间... - Robert
@Krishnabhadra 在看到你的解决方案之前,我花了将近一个小时来检查问题出在哪里...真的浪费了很多时间。在我的情况下,我将片段添加到一个没有setContentView()的空活动中。它也什么都不显示,只有一个空的黑色区域。非常感谢你指出这个问题! - Robert
备注:在添加时,需要检查片段是否已经被创建。 - stdout

8
你尝试使用 ft.replace(R.id.fragment_container, fragment) 来替换add吗? 使用 add 不会删除现有的fragment。

1
即使 add 操作不移除现有的 fragment,secondfragment 应该显示在第一个 fragment 上面吗?如果不是,那么这个 fragment transaction 有什么用?根据你的答案,当我使用 replace 而不是 add 时,第二个 fragment 没有显示。 - Krishnabhadra
所以我们需要移除、创建片段,就像我们向布局中添加和移除一样。那么 FragmentTransaction 的用途是什么? - Krishnabhadra
由于片段没有默认的堆叠方式,当一个片段离开屏幕时,它就会立即被销毁。因此,当我从片段A转到B,然后返回A时,我需要从头开始创建A,对吗? - Krishnabhadra
关于您的第一个问题,FragmentTransaction 用于在运行时添加/删除/替换特定布局中的片段。没有默认堆栈,但是您可以通过调用 addToBackStack(string) 将特定片段事务添加到后退堆栈,然后使用 FragmentManager 弹出堆栈。 - Sujai Kamat

2

您正在尝试在fragment_container中添加一个更多的片段,它正在添加但是由于您已经为id_first_fragment指定了fill_parent的宽度和高度, 所以该片段不可见,请尝试将id_first_fragment片段设置为wrap_content。当您单击按钮时,可以看到下一个片段。如果您想关闭第一个片段并显示第二个片段,则需要使用替换而不是添加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接