以编程方式返回回堆栈中的前一个片段

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

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

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

我发现Android中按钮点击时触发后退按钮功能,但我认为模拟一个返回键事件不是正确的方式去做它(我也不能让它工作):

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

调用finish()只是关闭我不感兴趣的活动。

还有更好的办法吗?

341980 次浏览

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

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

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

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

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

应该包含.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,并移回当前屏幕。

使用下面的代码以编程方式返回到前面的片段。

if ( getFragmentManager().getBackStackEntryCount() > 0)
{
getFragmentManager().popBackStack();
return;
}
super.onBackPressed();
将这些行添加到onBackPressed()方法中。popBackStackImmediate()方法会让你回到之前的片段,如果你有任何片段在后面的堆栈 ' < / p >
if(getFragmentManager().getBackStackEntryCount() > 0){
getFragmentManager().popBackStackImmediate();
}
else{
super.onBackPressed();
}

当你想关闭应用程序时,当你在主片段中向后按下时,这个解决方案非常适合基于底部栏的片段导航。

另一方面,当你打开二级片段(片段中的片段),在我的代码中定义为“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();

要使该片段再次出现,只需将该片段添加到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();
}
}
});

在上面的例子中,当Button button被按下时,我正在打开LoginFragment,现在用户在SignupFragment中。因此,如果调用addToBackStack(TAG),其中TAG = "SignupFragment",那么当返回按钮在LoginFragment中按下时,我们会回到SignUpFragment

编码快乐!

通过在最后一个片段上添加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();
}
});

试试下面的代码:

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

这些答案不工作,如果我没有addToBackStack()添加到我的片段事务,但是,你可以使用:

getActivity().onBackPressed();

从你的任何一个片段往回走一步;

我来到这里寻找或相同的想法,同时我提出了自己的,我相信不是那么糟糕,如果与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)

对于我的情况,2个片段在viewPager没有标签,它的工作很好。

芬兰湾的科特林回答

  1. 首先,调用片段的经理
  2. 之后,使用onBackPressed() 李方法。< / >

使用Kotlin在Android Studio 4.0中编码:

fragmentManager?.popBackStack()

Android导航架构组件。

下面的代码为我工作:

findNavController().popBackStack()

以下芬兰湾的科特林代码对我有用

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

 getActivity().onBackPressed();