简体   繁体   English

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

[英]Programmatically go back to the previous fragment in the backstack

Say I have an activity that has fragments added programmatically:假设我有一个以编程方式添加片段的活动:

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

What is the best way to return to the previous fragment that was visible?返回上一个可见片段的最佳方法是什么?

I found Trigger back-button functionality on button click in Android but I'm thinking simulating a back key event isn't the right way to go about it (and I can't get it to work either):我发现在 Android 中单击按钮时触发后退按钮功能,但我认为模拟后退键事件不是正确的方法(我也无法让它工作):

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

Calling finish() just closes the activity which I'm not interested in.调用finish()只会关闭我不感兴趣的活动。

Is there a better way to go about this?有没有更好的方法来解决这个问题?

Look at the getFragmentManager().popBackStack() methods (there are several to choose from)查看getFragmentManager().popBackStack()方法(有几种可供选择)

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

To elaborate on the other answers provided, this is my solution (placed in an Activity):为了详细说明提供的其他答案,这是我的解决方案(放置在活动中):

@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();  
    }
}

When we are updating/add the fragments,当我们更新/添加片段时,

Should Include the .addToBackStack() .应该包括.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();

After that if we give the getFragments.popBackStackImmediate() will return true if we add/update the fragments, and move back to the current screen.之后,如果我们添加/更新片段,则getFragments.popBackStackImmediate()将返回 true,然后返回当前屏幕。

Android Navigation architecture component. Android 导航架构组件。

The following code works for me:以下代码适用于我:

findNavController().popBackStack()

These answers does not work if i don't have addToBackStack() added to my fragment transaction but, you can use:如果我没有将 addToBackStack() 添加到我的片段事务中,这些答案将不起作用,但是您可以使用:

getActivity().onBackPressed();

from your any fragment to go back one step;从你的任何一个片段往后退一步;

Add those line to your onBackPressed() Method.将这些行添加到您的 onBackPressed() 方法中。 popBackStackImmediate() method will get you back to the previous fragment if you have any fragment on back stack ` popBackStackImmediate() 方法会让你回到前一个片段,如果你在后栈上有任何片段`

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

` `

This solution works perfectly for bottom bar based fragment navigation when you want to close the app when back pressed in primary fragment.当您想要在主片段中按下时关闭应用程序时,此解决方案非常适用于基于底部栏的片段导航。

On the other hand when you are opening the secondary fragment (fragment in fragment) which is defined as "DetailedPizza" in my code it will return the previous state of primary fragment.另一方面,当您打开在我的代码中定义为“DetailedPizza”的次要片段(片段中的片段)时,它将返回主要片段的先前状态。 Cheers !干杯!

Inside activities on back pressed put this:背面的内部活动放了这个:

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);
}

And launch the other fragment like this:并像这样启动另一个片段:

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

Kotlin Answer科特林答案

  1. First, call Fragment Manager .首先,调用Fragment Manager
  2. After, to use onBackPressed() method.之后,使用onBackPressed()方法。

Coding in Android Studio 4.0 with Kotlin:使用 Kotlin 在 Android Studio 4.0 中编码:

fragmentManager?.popBackStack()

Programmatically go back to the previous fragment using following code.使用以下代码以编程方式返回上一个片段。

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

To make that fragment come again, just add that fragment to backstack which you want to come on back pressed, Eg:要使该片段再次出现,只需将该片段添加到您想要返回的 backstack 中,例如:

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();
        }
    }
});

In the above case, I am opening LoginFragment when Button button is pressed, right now the user is in SignupFragment .在上述情况下,我在按下Button button时打开LoginFragment ,现在用户在SignupFragment中。 So if addToBackStack(TAG) is called, where TAG = "SignupFragment" , then when back button is pressed in LoginFragment , we come back to SignUpFragment .因此,如果addToBackStack(TAG) ,其中TAG = "SignupFragment" ,那么当在LoginFragment中按下后退按钮时,我们会回到SignUpFragment

Happy Coding!快乐编码!

By adding fragment_tran.addToBackStack(null) on last fragment, I am able to do come back on last fragment.通过在最后一个片段上添加fragment_tran.addToBackStack(null) ,我可以返回最后一个片段。

adding new fragment :添加新片段

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();
        }
    });

Following Kotlin code useful to me遵循对我有用的Kotlin代码

1. Added in Simple Activity class with multiple fragments used 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. Added in BottomNavigationView Activity class with multiple fragments used 2.在BottomNavigationView Activity类中添加了多个片段

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()
        }
    }
}

I came here looking or the same idea, and in the meantime i came up with own, which I believe is not that bad and works if with ViewPager.我来到这里寻找或相同的想法,同时我想出了自己的想法,我相信这还不错,如果与 ViewPager 一起使用。

So what I did, is to override the onBackPressed method in the parent activity that holds the viewPager, and set it to always go back minus 1 position until it reaches the first fragment, then closes the activity.所以我所做的是重写包含 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();
}

This might have a downfalls, like it only goes back one way left each time, so it might not work great if there are tabs and you switch positions with fragments skipped, ( going from 0 to 2, and then pressing back would put you on 1, instead of 0)这可能有一个缺点,就像它每次只返回一个方向,所以如果有标签并且你切换位置并跳过片段,它可能不会很好用,(从 0 到 2,然后按回会让你1,而不是 0)

For my case tho, with 2 fragments in viewPager without tabs, it does the job nicely.对于我的情况,viewPager 中有 2 个片段没有标签,它可以很好地完成工作。

Try below code:试试下面的代码:

@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();
            }
        }
    }
getActivity().getSupportFragmentManager().popBackStackImmediate();

或者

 getActivity().onBackPressed();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM