以编程方式返回到Backstack中的上一个片段

时间:2012-06-02 15:28:53

标签: android android-fragments back-stack

假设我有一个以编程方式添加了片段的活动:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

返回上一个可见片段的最佳方法是什么?

我找到了Trigger back-button functionality on button click in Android,但我认为模拟后退键事件不是正确的方法(我也无法让它工作):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

致电finish()只会关闭我不感兴趣的活动。

有没有更好的方法来解决这个问题?

14 个答案:

答案 0 :(得分:321)

查看getFragmentManager().popBackStack()方法(有几种方法可供选择)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack()

答案 1 :(得分:119)

详细说明提供的其他答案,这是我的解决方案(放在活动中):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}

答案 2 :(得分:24)

当我们更新/添加片段时,

应包括.addToBackStack()

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

之后,如果我们提供getFragments.popBackStackImmediate()将返回true,如果我们添加/更新片段,然后返回当前屏幕。

答案 3 :(得分:8)

将这些行添加到onBackPressed()方法中。如果后端堆栈上有任何片段,popBackStackImmediate()方法将返回到上一个片段 `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`

答案 4 :(得分:4)

当您想要在主片段中按下后关闭应用时,此解决方案非常适用于基于底部条的片段导航。

另一方面,当您打开我的代码中定义为“DetailedPizza”的辅助片段(片段中的片段)时,它将返回先前的主片段状态。干杯!

背面的内部活动把这个:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

    if (home instanceof FragmentDetailedPizza && home.isVisible()) {
        if (getFragmentManager().getBackStackEntryCount() != 0) {
            getFragmentManager().popBackStack();
        } else {
            super.onBackPressed();
        }

    } else {
        //Primary fragment
        moveTaskToBack(true);
    }

然后启动另一个片段:

Fragment someFragment = new FragmentDetailedPizza();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
    transaction.addToBackStack("DetailedPizza");
    transaction.commit();

答案 5 :(得分:2)

如果我没有在片段事务中添加addToBackStack(),这些答案将不起作用,但是,您可以使用:

getActivity().onBackPressed();

从您的任何片段返回上一步;

答案 6 :(得分:1)

使用以下代码以编程方式返回上一个片段。

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

答案 7 :(得分:1)

要使该片段再次出现,只需将该片段添加到您想要返回的背板上,例如:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

在上述情况下,我在按下LoginFragment时打开Button button,此时用户位于SignupFragment。因此,如果addToBackStack(TAG)被调用,TAG = "SignupFragment",那么当在LoginFragment中按下后退按钮时,我们会回到SignUpFragment

快乐的编码!

答案 8 :(得分:1)

我来这里的目的或想法是相同的,与此同时,我想出了自己的想法,我认为这还不错,并且可以与ViewPager一起使用。

所以我要做的是在保存viewPager的父活动中重写onBackPressed方法,并将其设置为始终返回负1位置,直到到达第一个片段,然后关闭该活动。

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

这可能会导致崩溃,就像每次都只向左退回一样,因此,如果有标签页并且您跳过片段切换位置(从0到2,然后按回车,则可能效果不佳)将您置于1,而不是0)

对于我来说,在viewPager中有2个不带制表符的片段,它做得很好。

答案 9 :(得分:1)

2020年7月16日-Kotlin回答

  1. 首先,调用 Fragment Manager
  2. 之后,要使用 onBackPressed() 方法。

使用Kotlin在Android Studio 4.0中进行编码:

fragmentManager?.popBackStack()

祝您编程愉快!

@canerkaseler

答案 10 :(得分:1)

Android Studio 4.0.1 Kotlin 1.3.72

Android导航架构组件。

以下代码对我有用:

findNavController().popBackStack()

答案 11 :(得分:0)

通过在最后一个片段上添加fragment_tran.addToBackStack(null),我可以返回到最后一个片段。

添加新片段

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });

答案 12 :(得分:0)

尝试以下代码:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }

答案 13 :(得分:0)

以下对我有用的Kotlin代码

1.在使用多个片段的简单活动类中添加

override fun onBackPressed() {
    if (supportFragmentManager.backStackEntryCount > 0) {
        Log.i(TAG, "=============onBackPressed - Popping backstack====")
        supportFragmentManager.popBackStack()
    } else {
        Log.i(TAG, "=============onBackPressed called because nothing on backstack====")
        super.onBackPressed()
    }
}

2.在 BottomNavigationView 使用多个片段的活动类中添加

override fun onBackPressed() {

    Log.e(TAG, "=============onBackPressed")
    val navController = findNavController(R.id.nav_host_fragment)
    when (navController.currentDestination!!.id) {
        R.id.navigation_comments, R.id.navigation_my_posts -> {
            menuItemPosition = 0
            navController.navigate(R.id.navigation_home)
            Log.i(TAG, "=============onBackPressed - Popping backstack with First fragment ====")
        }
        else -> {
            Log.i(TAG, "=============onBackPressed called because nothing on backstack====")
            super.onBackPressed()
        }
    }
}