无论如何交换或重新排序片段 BackStack 条目?
Is there anyway to swap or reorder fragment BackStack entry?
正在创建多个片段应用程序,这需要轻松更改片段选项卡,必须保留其 BackStack 条目。用户点击片段必须立即弹出。我认为重新排序 BackStack 是最好的选择。有人知道如何重新排序 BackStack 吗?
我有 5 个片段 A、B、C、D、E。如果用户打开像 A ---> B ---> C ---> D ---> E 这样的片段。使用默认的后退堆栈,后退键可以正常工作。但是当用户打开 A ---> B ---> C ---> D ---> E ---> B 之后,如果用户点击返回,默认返回堆栈将转到 A.
这个用例没有 api,但有其他方法可以这样做:
例子
用户沿着路径 A ---> B ---> C ---> D ---> E
然后他想来到 B
。所以你应该做的是:
- 检查
B
是否已经在返回堆栈中。
- 如果存在,则
popBackStackImmediate
到return到B
- 如果没有,则正常添加片段
B
。
所以替换片段应该是这样的:
public void replaceFragment(Fragment fragment) {
String fragmentTag = fragment.getClass().getCanonicalName(); //unique name for the fragment, which will be used as tag.
FragmentManager fragmentManager = getSupportFragmentManager();
boolean isPopped = fragmentManager.popBackStackImmediate(fragmentTag, 0); // trying to return to the previous state of B if it exists.
if (!isPopped && fragmentManager.findFragmentByTag(fragmentTag) == null){ // fragment is not in the backstack, so create it.
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.frame_layout, fragment, fragmentTag);
ft.addToBackStack(fragmentTag);
ft.commit();
}
}
记住,这将 return 到 B
的 以前的状态 。
提示:由于您不想要任何片段的两个实例,因此请尝试为它们创建一个单例实例。因为,如果您正在创建片段的新实例并且该片段已经存在于返回堆栈中,那么新实例将被忽略(因为您正在 return 返回到以前的状态)。
你可以试试这个...
onBackpressed
@Override
public void onBackPressed() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.frame_container);
if (f instanceof FragmentE)
{
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-1).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else if (f instanceof FragmentD) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else if (f instanceof FragmentC) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-3).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else if (f instanceof FragmentB) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-4).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else
{
super.onBackPressed();
}
}
for back remove stack
final android.app.FragmentManager fm = getFragmentManager();
fm.addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() ==0) {
// dLayout.closeDrawers();
finish();
}
else
{
// dLayout.closeDrawers();
}
}
});
只有在之前没有添加片段时才可以调用addToBackstack()
假设在您的情况下,当用户在片段 E 中并且当用户调用片段 B 时检查片段 B 是否已添加到返回堆栈中
如果是,则不要为该 FragmentTransaction 调用 addToBackstack。
否则,调用 addToBackstack()
检查我的示例代码:
private void addFragment (Fragment fragment){
boolean isFragment=false;
String backStateName = fragment.getClass().getName();
FragmentManager fm = getFragmentManager();
for(int entry = 0; entry < fm.getBackStackEntryCount(); entry++){
Log.i(TAG, "Found fragment: " + fm.getBackStackEntryAt(entry).getId());
if(fm.getBackStackEntryAt(entry).getId().equalsIgnoreCase(FragmentB))// check if fragment is in back stack
{
isFragment=true;
}
}
if (!isFragment){ //fragment added to back stack, create it.
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, FragmentB).addToBackStack(FragmentB).commit();
}else {//else dont call addToBackStack()
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, FragmentB).commit();
}
}
只需将此代码放入您的 MainActivity
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
//super.onBackPressed();
if (getFragmentManager().getBackStackEntryCount() == 1) {
finish();
}
getFragmentManager().popBackStack();
}
}
这里getFragmentManager().getBackStackEntryCount() == 0
会检查堆栈入口是否为0,如果为0则Activity结束。
在你的情况下 A --> B --> C --> D --> E --> B
A 将在 0,
B 将在 1,
C 上 2,
D 上 3,
E 上 4,
B 上 5
因此,当您单击返回时,if
条件将检查返回堆栈计数是否为 0。
使用不可滑动的 viewpager 并在 addOnPageChangeListener 上创建数组列表并保存所有打开的页面。 onBackPressed 将比较数组列表并显示页面。
正在创建多个片段应用程序,这需要轻松更改片段选项卡,必须保留其 BackStack 条目。用户点击片段必须立即弹出。我认为重新排序 BackStack 是最好的选择。有人知道如何重新排序 BackStack 吗?
我有 5 个片段 A、B、C、D、E。如果用户打开像 A ---> B ---> C ---> D ---> E 这样的片段。使用默认的后退堆栈,后退键可以正常工作。但是当用户打开 A ---> B ---> C ---> D ---> E ---> B 之后,如果用户点击返回,默认返回堆栈将转到 A.
这个用例没有 api,但有其他方法可以这样做:
例子
用户沿着路径 A ---> B ---> C ---> D ---> E
然后他想来到 B
。所以你应该做的是:
- 检查
B
是否已经在返回堆栈中。 - 如果存在,则
popBackStackImmediate
到return到B
- 如果没有,则正常添加片段
B
。
所以替换片段应该是这样的:
public void replaceFragment(Fragment fragment) {
String fragmentTag = fragment.getClass().getCanonicalName(); //unique name for the fragment, which will be used as tag.
FragmentManager fragmentManager = getSupportFragmentManager();
boolean isPopped = fragmentManager.popBackStackImmediate(fragmentTag, 0); // trying to return to the previous state of B if it exists.
if (!isPopped && fragmentManager.findFragmentByTag(fragmentTag) == null){ // fragment is not in the backstack, so create it.
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.frame_layout, fragment, fragmentTag);
ft.addToBackStack(fragmentTag);
ft.commit();
}
}
记住,这将 return 到 B
的 以前的状态 。
提示:由于您不想要任何片段的两个实例,因此请尝试为它们创建一个单例实例。因为,如果您正在创建片段的新实例并且该片段已经存在于返回堆栈中,那么新实例将被忽略(因为您正在 return 返回到以前的状态)。
你可以试试这个...
onBackpressed
@Override
public void onBackPressed() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.frame_container);
if (f instanceof FragmentE)
{
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-1).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else if (f instanceof FragmentD) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else if (f instanceof FragmentC) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-3).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else if (f instanceof FragmentB) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-4).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
else
{
super.onBackPressed();
}
}
for back remove stack
final android.app.FragmentManager fm = getFragmentManager();
fm.addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() ==0) {
// dLayout.closeDrawers();
finish();
}
else
{
// dLayout.closeDrawers();
}
}
});
只有在之前没有添加片段时才可以调用addToBackstack()
假设在您的情况下,当用户在片段 E 中并且当用户调用片段 B 时检查片段 B 是否已添加到返回堆栈中
如果是,则不要为该 FragmentTransaction 调用 addToBackstack。
否则,调用 addToBackstack()
检查我的示例代码:
private void addFragment (Fragment fragment){
boolean isFragment=false;
String backStateName = fragment.getClass().getName();
FragmentManager fm = getFragmentManager();
for(int entry = 0; entry < fm.getBackStackEntryCount(); entry++){
Log.i(TAG, "Found fragment: " + fm.getBackStackEntryAt(entry).getId());
if(fm.getBackStackEntryAt(entry).getId().equalsIgnoreCase(FragmentB))// check if fragment is in back stack
{
isFragment=true;
}
}
if (!isFragment){ //fragment added to back stack, create it.
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, FragmentB).addToBackStack(FragmentB).commit();
}else {//else dont call addToBackStack()
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, FragmentB).commit();
}
}
只需将此代码放入您的 MainActivity
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
//super.onBackPressed();
if (getFragmentManager().getBackStackEntryCount() == 1) {
finish();
}
getFragmentManager().popBackStack();
}
}
这里getFragmentManager().getBackStackEntryCount() == 0
会检查堆栈入口是否为0,如果为0则Activity结束。
在你的情况下 A --> B --> C --> D --> E --> B
A 将在 0,
B 将在 1,
C 上 2,
D 上 3,
E 上 4,
B 上 5
因此,当您单击返回时,if
条件将检查返回堆栈计数是否为 0。
使用不可滑动的 viewpager 并在 addOnPageChangeListener 上创建数组列表并保存所有打开的页面。 onBackPressed 将比较数组列表并显示页面。