如何使用按钮关闭当前片段,就像使用返回按钮一样?

120

我尝试使用ImageButton关闭当前片段。

我在片段A中,当我点击按钮时它会转到片段B。

当我在片段B中点击按钮时,它会转到片段C并关闭片段B。

如果我在片段C中点击返回按钮,它会返回到片段A。

我尝试的代码如下:

camera_album = (ImageButton) view.findViewById(R.id.camera_album);

camera_album.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {

                    closefragment();
        Fragment fragment = FileBrowserFragment.newInstance(null, null, null) ;
        MainActivity.addFragment(LocalFileBrowserFragment.this, fragment) ;


    }
});

private void closefragment() {
    getActivity().getFragmentManager().beginTransaction().remove(this).commit();
}

当我在Fragment-B页面点击返回按钮时,它会跳转到Fragment-C页面。

但是当我在Fragment-C页面点击返回按钮时,它不会回到Fragment-A页面,而是回到了一个空白的背景。如果我想回到Fragment-A页面,我必须再次点击返回按钮。

因此,似乎没有完全关闭当前的fragment。

如何像Android的返回按钮一样完成当前的fragment?


这个 MainActivity.addFragment(LocalFileBrowserFragment.this, fragment) 是什么?你需要将该片段添加到返回栈中,并相应地弹出。 - Raghunandan
在addFragment函数中已经添加了片段。 - Wun
将Fragment添加到哪里和Activity方法中? - Raghunandan
2
getActivity().onBackPressed(); 可以做到这一点。 - Viswanath Lekshmanan
14个回答

177

我已经将代码从原来的形式进行了修改。

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

getActivity().getFragmentManager().popBackStack();

它会弹出顶部的碎片


这对我有用:context.supportFragmentManager.beginTransaction().remove(this@MyFragment).commit() - Faizan Haidar Khan
使用类型为androidx.fragment.app.Fragment的片段,似乎会保留片段标题。因此,我的主应用程序中弹出的片段标题仍然显示。对我来说,getActivity().onBackPressed() 更有效。 - Ben
3
不要忘记在“getFragmentManager()”无法正常工作时使用“getSupportFragmentManager()”。 - Joe Okatch
很遗憾,这已经过时了。 从现在开始,请使用 OnBackPressedCallback。 - Dominik

88

对于那些需要找到简单方法的人

尝试使用getActivity().onBackPressed();


getActivity() 可能会出现很多次为空的情况。 - Arpit J.
2
@ArpitJ. 在 onAttach() 被调用之前它只是 null,一个 fragment 不能独立存在于 activity 之外。 - Tamim Attafi
@TamimAttafi 是的,但我指的是像旋转或活动已经完成,由于某些原因片段实例仍然存在,那么它将返回null。 - Arpit J.
4
popBackStack()popBackStackImmediate()是直接弹出最上层片段的方法,而不需要模拟按钮按下。使用onBackPressed()会触发OnBackPressedCallback。如果将来您想特别处理后退按钮按下的情况,则必须切换到popBackStack()/ popBackStackImmediate()以避免程序化地触发回调函数。 - Nolan Amy
将此代码放入Fragment的按钮的onclick方法中。 - Anon
糟糕的解决方案。虽然它最初可以提供结果,但一旦你开始覆盖OnBackPress或者键盘打开等情况,你发起的返回操作只会关闭键盘而不是片段。这些只是你可能遇到的许多问题中的一部分。请使用User popBackStack()或popBackStackImmediate()。 - Itay Feldman

87

从片段A到B,将A替换为B并在commit()之前使用addToBackstack()

现在从片段B到C,首先使用popBackStackImmediate(),这将使A返回。现在像第一个事务一样用C替换A。


4
为了使用popStackImmediate() -> 调用getView().setOnKeyListener(new View.OnKeyListener() {...})方法,实现View.OnKeyListener接口并重写onKey()方法。 在onKey()方法中判断如果按下的键是返回键(KeyEvent.KEYCODE_BACK),则调用getActivity().getSupportFragmentManager().popBackStackImmediate()方法来弹出后退栈,并返回true;否则返回false。 - Yash Agrawal

6

试试这个:

public void removeFragment(Fragment fragment){
    android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
    android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    fragmentTransaction.remove(fragment);
    fragmentTransaction.commit();
}

5
你可以尝试这个逻辑,因为它对我有效。
frag_profile profile_fragment = new frag_profile();

boolean flag = false;
@SuppressLint("ResourceType")
public void profile_Frag(){
    if (flag == false) {
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        manager.getBackStackEntryCount();
        transaction.setCustomAnimations(R.anim.transition_anim0, R.anim.transition_anim1);
        transaction.replace(R.id.parentPanel, profile_fragment, "FirstFragment");
        transaction.commit();
        flag = true;
    }

}

@Override
public void onBackPressed() {
    if (flag == true) {
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        manager.getBackStackEntryCount();
        transaction.remove(profile_fragment);
        transaction.commit();
        flag = false;
    }
    else super.onBackPressed();
}

5

这是使用Kotlin进行操作的方法,我在Fragment布局中创建了一个按钮,然后在onViewCreated中设置了onClickListner。

根据@Viswanath-Lekshmanan的评论

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) 
{
     super.onViewCreated(view, savedInstanceState)

     btn_FragSP_back.setOnClickListener {
        activity?.onBackPressed()
    }
}

4
这将关闭活动而不是片段。 - nibbana
如果我们必须双击后退按钮才能关闭活动,我们该怎么做? - Codist

4
Button ok= view.findViewById(R.id.btSettingOK);
Fragment me=this;
ok.setOnClickListener( new View.OnClickListener(){
    public void onClick(View v){
     getActivity().getFragmentManager().beginTransaction().remove(me).commit();
    }
});

3
虽然这段代码可能回答了问题,但提供关于为什么和/或如何回答问题的额外上下文信息可以增加其长期价值。 - rollstuhlfahrer
1
这段简单的代码实际上通过一个“确定”或“关闭”按钮来移除当前片段视图。我用它来退出作为片段显示的轻量级设置面板并返回到活动中。很抱歉使用这个技巧,但在Android 8下,我认为管理多个片段不是很实用。 - Bruno L.

4

试试这个:

ft.addToBackStack(null);   // ft is FragmentTransaction

因此,当您按下“返回键”时,当前活动(包含多个片段)将加载先前的片段,而不是结束自身。

0
如果您需要更具体地处理后退按钮的操作,可以使用以下方法:
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if( keyCode == KeyEvent.KEYCODE_BACK )
        {
            onCloseFragment();
            return true;
        } else {
            return false;
        }
    }
});

0

移除当前碎片B并导航到堆栈返回(其他碎片A):

private fun navigateToBackStack() {
    requireActivity().supportFragmentManager
        .beginTransaction()
        .remove(this)
        .commit()
    requireActivity().supportFragmentManager.popBackStack()
}

GL


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