【问题标题】:Handling fragment backstack in Navigation drawer处理导航抽屉中的片段回栈
【发布时间】:2015-07-28 19:36:22
【问题描述】:

好吧,我知道还有其他 questions 乍一看让这个看起来像重复,但这些答案都不适用于我的情况,

我想要的是第一个片段显示为关于后退按钮如何工作的主活动,我需要从导航抽屉中选择的任何片段在按下后退按钮时返回到第一个片段用户再按一下就会退出应用程序。

所以我尝试使用 addToBackStack,当我移动到另一个片段时,如果我按下后退按钮,它会回到我的第一个片段(完全按照我的意愿),但再次按下后退按钮会让我看到白屏(我想知道是否这是由于我使用了下面包含的事务动画)所以为了解决这个问题,我尝试覆盖后退按钮并调用完成();但这会导致我所在的任何片段完成而不是返回到第一个片段,我从上述链接和许多其他链接中尝试了一些解决方法,但找不到合适的修复任何建议?

这是我的主要活动显示视图

 private void displayView(int position) {
    // update the main content by replacing fragments
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = new FirstFragment();

            break;

        case 1:
            fragment = new glideFrag();
            break;
        case 2:
            fragment = new secondGlideFrag();
            break;
        case 3:
            fragment = new thirdGlideFrag();
            break;
        case 4:
            fragment = new forthGlideFrag();
            break;

        case 5:
            fragment = new lgFrag();
            break;
        case 6:
            fragment = new cyanFrag();
            break;
        case 7:
            fragment = new sonyFrag();
            break;
        case 8:
            fragment = new SecondFragment();
            break;

        default:
            break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.setCustomAnimations(R.anim.enter,R.anim.exit,R.anim.pop_enter,R.anim.pop_exit);

        //fragmentManager.beginTransaction()
                fragmentTransaction.replace(R.id.frame_container, fragment).addToBackStack("first Fragment").commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(navMenuTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    } else {
        // error in creating fragment
        Log.e("MainActivity", "Error in creating fragment");
    }

我发现这是一个很好的解决方法

private boolean popNext = false;

  if(popNext){
        if(position == INITIAL_POSITION){
            onBackPressed();
            mDrawerLayout.closeDrawer(mDrawerList);
            popNext = false;
            return;
        }
        getSupportFragmentManager().popBackStackImmediate();
    }
    else{
        if(position == INITIAL_POSITION){
            mDrawerLayout.closeDrawer(mDrawerList);
            return;
        }
        popNext=true;
    }

但我对 android 还是很陌生,我不确定将 INITIAL_POSITION 设置为什么,我试过了

private static final INITIAL_POSITION = 0; 

但没有任何运气

【问题讨论】:

  • 这个已经问了很多次了。请搜索。
  • 我知道,我读过,我什至引用了一个

标签: android android-fragments fragment-backstack


【解决方案1】:

添加初始片段时,您必须将其添加到后堆栈。 你必须只为下一个做。当返回栈为空时,Activity 就结束了。

编辑:以下是对问题的解释,以便您找出解决方法:

每次将片段事务添加到返回堆栈时,您都允许用户通过按返回按钮将其还原,并且 Activity 将返回到事务之前的状态。如果 initial 片段被添加到返回栈中,那么当用户按下返回时,屏幕变为空白,因为在添加初始片段之前没有显示任何内容。这就是为什么将第一个可见片段添加到您的 Activity 的初始片段事务不能添加到后台堆栈的原因。通常你像这样初始化初始片段:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState == null) {
        Fragment fragment = new FirstFragment();
        getSupportFragmentManager().beginTransaction()
            .add(R.id.frame_container, fragment)
            .commit();
    }
}

【讨论】:

  • 所以在这种情况下,我在导航抽屉中拥有所有片段,我将在哪里调用我的第一个添加到后台堆栈?我应该改写 onBackPress 并调用活动,还是可以调用 popstack 方法?
  • 你不需要覆盖任何东西。默认情况下,当您按下返回时,系统会依次尝试这些操作: 1) 如果抽屉打开,则关闭抽屉。 2)如果片段不为空,则将片段返回堆栈。 3) 完成活动。
  • 您需要将 A 添加到后台堆栈,但您仍必须将 B 和 C 添加到后台堆栈。如果不为空,则按返回将弹出返回堆栈。
  • 这是我的意思,您不应该使用该代码初始化 A。当savedInstanceState 为空时,您应该添加特殊代码以在onCreate() 中添加A,并且不要将此初始事务添加到后台堆栈。然后,您可以将当前代码重用于以下事务。我不知道如何更好地解释它。
  • 我在回答中添加了对您的问题的更详细说明。
【解决方案2】:

BladeCoders 的回答更多是试图告诉我后退堆栈是如何工作的,而不是回答我的问题,我最终没有向后退堆栈添加任何片段,.addToBackStack(null),并覆盖 MainActivity 中的后退按钮,感觉有点有点小技巧,但效果很好

@Override
public void onBackPressed() {
    FragmentManager fragmentManager = getSupportFragmentManager();

if (fragmentManager.getBackStackEntryCount() < 1){
        Fragment fragment = new FirstFragment();
        FragmentTransaction fragmentTransaction =    
        getSupportFragmentManager().beginTransaction();
        fragmentTransaction.setCustomAnimations(R.anim.enter, R.anim.exit, 
        R.anim.pop_enter, R.anim.pop_exit);

        getSupportActionBar().setTitle(mDrawerTitle);

        fragmentTransaction.replace(R.id.frame_container, 
        fragment).addToBackStack("first").commit();

    }else{
        finish();
    }
}

【讨论】:

  • 作为记录,.addToBackStack(null) 仍然将事务添加到后台堆栈,它只是没有与标签关联。是的,您的解决方案确实是不必要的黑客攻击。
  • 另外,如果你想让 ActionBar 的标题与当前显示的片段同步,你可以使用 FragmentManager.addOnBackStackChangedListener() 设置一个 backstack 监听器并在那里更改标题。
【解决方案3】:

即使没有 backstack,您也可以做到这一点,这只是我简化的观点,以便它可以帮助某些人。

 @Override
public void onBackPressed(){

    Fragment f = getSupportFragmentManager().findFragmentById(R.id.container_body);
    if(f.getClass().getName().equals(HomeFragment.class.getName())){ // here HomeFragment.class.getName() means from which faragment you actually want to exit
        finish();
    }else{
        displayView(0);  //were you want to go when back button is pressed
    }

}





private void displayView(int position) {
    Fragment fragment = null;
    String title = getString(R.string.app_name);
    switch (position) {
        case 0:
            fragment = new HomeFragment();
            title = getString(R.string.app_name);
            break;
        case 1:
            fragment = new OffersFragment();
            title = getString(R.string.nav_item_offers);
            break;
        case 2:
            fragment = new NotificationFragment();
            title = getString(R.string.nav_item_notifications);
            break;

        default:
            break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.container_body, fragment);
        fragmentTransaction.commit();

        // set the toolbar title
        getSupportActionBar().setTitle(title);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    • 2014-01-17
    • 1970-01-01
    相关资源
    最近更新 更多