FragmentTransaction 没有做任何事情

Posted

技术标签:

【中文标题】FragmentTransaction 没有做任何事情【英文标题】:FragmentTransaction not doing anything 【发布时间】:2012-09-07 05:41:54 【问题描述】:

我正在学习片段,下面给出的是我的第一个片段程序。一个简单的项目,我有 2 个屏幕。当我单击第一个屏幕的下一个按钮时,需要显示第二个按钮。

我的目标是 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_ android:layout_
  android:orientation="vertical" android:id="@+id/fragment_container">

   <fragment class="com.research.fragmentstudy.FirstFragment"     
      android:layout_
      android:layout_ 
      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();
     
  ;

first_fragment_layout.xml

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

   <TextView android:layout_ 
       android:layout_
       android:text="Fragment 1" android:gravity="center_horizontal" />

   <Button android:layout_ 
       android:layout_gravity="center_horizontal"
       android:layout_ 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_ android:layout_
   android:orientation="vertical" android:id="@+id/first_fragment_root">

   <TextView android:layout_ 
      android:layout_
      android:text="Fragment 2" android:gravity="center_horizontal" />

</LinearLayout>

嗯,我的第一个屏幕没问题。现在,

根据我对片段的理解,我所期望的

当我单击屏幕 1 中的下一步按钮时,会创建 SecondFragment, 它的 onCreate()onCreateView() 被调用。 SecondFragment 显示,FirstFragment 被销毁(因为我是 不将其添加到后台堆栈)。以后不会有动画了 默认片段事务没有动画。

发生了什么

SecondFragment 正在正常创建,它的 onCreate()onCreateView() 被调用。 但 FirstFragment 仍保留在屏幕上,第二个从未显示。

现在我对片段的理解可能是错误的。但是我相信当我们 commit() 一个片段事务时,第一个片段应该被第二个片段替换(第一个片段要么被隐藏要么被破坏)。好吧,似乎什么都没有发生。这是为什么?我们应该手动销毁/隐藏第一个片段吗?

注意:我知道对于这样一个基本的事情来说这是一个很长的问题。但是我把我的整个代码都放了,因为我不确定我在哪里搞砸了。

【问题讨论】:

【参考方案1】:

好吧,我让它工作了。对这个问题的两个答案都正确地说明了我的代码无法按预期工作的一个原因。但我的代码中有 2 个错误。

使用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_ android:layout_
  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);工作……浪费时间…… @Krishnabhadra 我的意思是在我看到你的解决方案之前,花了将近一个小时来检查出了什么问题......真的很浪费时间。就我而言,我将片段添加到没有 setContentView() 的空活动中。它也只显示空白的黑色区域。非常感谢您指出这一点! 备注:添加时需要检查之前是否创建过fragment。【参考方案2】:

您是否尝试过使用 ft.replace(R.id.fragment_container, fragment) 而不是 add ? add 不会删除现有的片段。

【讨论】:

即使 add 不会删除现有的片段,第二个片段是否应该在屏幕上比第一个片段可见?如果不是,这个片段事务有什么用?关于你的回答,当我使用替换而不是添加时,第二个片段没有显示。 所以我们需要删除,创建片段,就像我们在布局中添加和删除一样。那么这个 FragmentTransaction 有什么用呢? 由于没有默认的fragment堆叠,当一个fragment离开屏幕时,它就被销毁了。因此,当我将片段 A 转到 B 并返回到 A 时,我需要从头开始创建 A 对吗? 关于您的第一个问题,FragmentTransaction 用于在运行时在特定布局中添加/删除/替换片段。没有默认堆叠,但您可以通过调用 addToBackStack(string) 和使用 Fragment manager 弹出堆栈将特定片段事务添加到后台堆栈【参考方案3】:

您正在尝试在 fragment_container 中再添加一个片段,它正在添加,但您的片段不可见,因为您已将 id_first_fragment 的宽度和高度指定为 fill_parent,因此请尝试为 id_first_fragment 片段设置 wrap_content 。单击按钮时,您可以看到下一个片段。如果要关闭第一个片段并显示第二个片段,则需要 replace 而不是 add 。

【讨论】:

以上是关于FragmentTransaction 没有做任何事情的主要内容,如果未能解决你的问题,请参考以下文章

FragmentManager和FragmentTransaction到底做了什么?

FragmentTransaction.remove 没有效果

android,在先做了popStack之后,如何避免用FragmentTransaction替换片段时出现闪烁

新的 FragmentTransaction commitNow() 在内部如何工作?

FragmentManager 和 FragmentTransaction 到底是做啥的?

FragmentTransaction的add(),replace(),以及show(),hide()