如何让Fragment自行删除,即它相当于finish()?

时间:2011-05-05 16:44:25

标签: android

我正在使用兼容性库转换应用程序以使用片段。 现在我有许多活动(A B C D)互相链接,D有一个按钮'OK',按下后调用完成,然后通过onActivityResult()冒泡,另外销毁C和B.

对于我的前Honycomb片段版本,每个活动实际上是片段Af Bf Cf Df的包装器。所有活动均通过startActivityForResult()启动,每个片段中的onActivityResult()可以愉快地致电getActivity().finish()

我遇到的问题是在我的Honeycomb版本中我只有一个活动A,并且使用FragmentManager加载片段Bf,Cf,Df。

我不明白的是,当按下“确定”以删除片段Df,Cf和Bf时,在Df中该怎么办?

我尝试让片段从堆栈中弹出,但这会导致异常。 onActivityResult()没用,因为我没有使用startActivityForResult()加载片段。

我是否完全以错误的方式思考这个问题?我是否应该实现某种与父片段或活动进行通信的侦听器,以便使用事务管理器进行弹出?

12 个答案:

答案 0 :(得分:308)

虽然它可能不是最好的方法,但我能想到的最接近的等价物是支持/兼容性库

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

getActivity().getFragmentManager().beginTransaction().remove(this).commit();

否则。

此外,您可以使用backstack并弹出它。但请记住,片段可能不在backstack上(取决于在那里获得它的片段事务..)或者它可能不是最后一个进入堆栈,因此弹出堆栈可能会删除错误的...

答案 1 :(得分:55)

  

我不明白的是,当按下“确定”以删除片段Df,Cf和Bf时,在Df中该怎么做?

步骤#1:让Df告诉D“哟!我们得到了OK点击!”通过调用方法,在活动本身或活动提供的接口实例上。

步骤2:让D通过FragmentManager删除片段。

托管活动(D)是知道活动中其他片段(与其他活动相比)的活动。因此,可能会影响片段混合的片段内事件应该传播到活动,这将使适当的编排移动。

答案 2 :(得分:35)

你应该让Activity处理添加和删除片段,正如CommonsWare所说,使用一个监听器。这是一个例子:

public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {

    // onCreate etc

    @Override
    public void onFragmentSuicide(String tag) {
        // Check tag if you do this with more than one fragmen, then:
        getSupportFragmentManager().popBackStack();
    }
}

public interface SuicidalFragmentListener {
    void onFragmentSuicide(String tag);
}

public class MyFragment extends Fragment {

    // onCreateView etc

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
           suicideListener = (SuicidalFragmentListener) activity;
        } catch (ClassCastException e) {
           throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Attach the close listener to whatever action on the fragment you want
        addSuicideTouchListener();
    }

    private void addSuicideTouchListener() {
        getView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              suicideListener.onFragmentSuicide(getTag());
            }
        });
    }
}

答案 3 :(得分:17)

在Activity / AppCompatActivity中:

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
        // if you want to handle DrawerLayout
        mDrawerLayout.closeDrawer(GravityCompat.START);
    } else {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }
}

然后调用片段:

getActivity().onBackPressed();

或者像其他答案中所说的那样,在片段中调用它:

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

答案 4 :(得分:4)

查看DialogFragment是否满足您的需求。 DialogFragment有一个dismiss()方法。我认为更清洁。

答案 5 :(得分:3)

我为此创建了简单的方法

popBackStack(getSupportFragmentManager());

将其放在我的ActivityUtils类

public static void popBackStack(FragmentManager manager){
        FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
        manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

这很棒,玩得开心!

答案 6 :(得分:1)

如果您需要从Backstack历史记录中的第四个片段弹回到第一个片段,请使用标签!!!

当您添加第一个片段时,您应该使用以下内容:

getFragmentManager.beginTransaction.addToBackStack("A").add(R.id.container, FragmentA).commit() 

getFragmentManager.beginTransaction.addToBackStack("A").replace(R.id.container, FragmentA).commit()

当你想要显示碎片B,C和D时,你可以使用它:

getFragmentManager.beginTransaction.addToBackStack("B").replace(R.id.container, FragmentB, "B").commit()

和其他信件......

要返回Fragment A,只需调用popBackStack(0, "A"),是的,使用添加时指定的标志,并注意它必须与命令{{1}中的标志相同},而不是命令中使用的替换或添加。

欢迎你;)

答案 7 :(得分:1)

OnCreate中:

//Add comment fragment
            container = FindViewById<FrameLayout>(Resource.Id.frmAttachPicture);
            mPictureFragment = new fmtAttachPicture();

            var trans = SupportFragmentManager.BeginTransaction();
            trans.Add(container.Id, mPictureFragment, "fmtPicture");
            trans.Show(mPictureFragment); trans.Commit();

这就是我在点击事件1中隐藏片段的方式

//Close fragment
    var trans = SupportFragmentManager.BeginTransaction();
    trans.Hide(mPictureFragment);
    trans.AddToBackStack(null);
    trans.Commit();

然后将其显示回事件2

var trans = SupportFragmentManager.BeginTransaction();
            trans.Show(mPictureFragment); trans.Commit();

答案 8 :(得分:0)

如果您使用的是新的导航组件,则很简单

findNavController().popBackStack()

它将为您完成所有的FragmentTransaction。

答案 9 :(得分:0)

在同一片段内关闭片段

getActivity().onBackPressed();

答案 10 :(得分:-1)

parentFragmentManager.apply {
    val f = this@MyFragment
    beginTransaction().hide(f).remove(f).commit()
}

答案 11 :(得分:-7)

为什么不只是:

getActivity()。finish();