【问题标题】:Fragment Backstack片段后栈
【发布时间】:2015-03-10 21:46:35
【问题描述】:

您好,我有一个活动和三个片段。当我替换我的第一个片段时,我将它添加到 backstack。

FragmentTransaction fragmentTransaction = getFragmentManager()
            .beginTransaction();
fragmentTransaction.replace(R.id.authentication_parent0_linear,
                new LoginFragment(), LOGINTAG);
fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

但是当我在其他两个片段之间移动时,我不会将它们添加到 backstack。所以每当我从其他两个片段返回时,我需要返回到第一个片段。当我删除第一个片段并添加第二个片段时它工作正常片段或首先删除并添加第三个,即当我按回时,我将回到第一个片段。但是当我在删除第二个并添加第三个或删除第三个并添加第二个等这两个片段之间导航时。在那种情况下,当我按下返回时,我正在退出应用程序,并且 backstackcount 显示为零,但是当我第一次删除第一个片段时,我将它存储在 backstack 中。

getFragmentManager()
            .beginTransaction()
            .replace(R.id.authentication_parent0_linear,
                    new SignupFragment(), SIGNUPTAG).commit();

所以我的问题是片段回栈是否会在提交之间重置。如果是这样,我怎样才能第一次在后台获取存储的片段

【问题讨论】:

  • 让我了解您想要实现的目标。您有片段 A、B、C。您从片段 A 开始。从这一点开始,您希望在任何导航路径后用户按下后退都会将用户带到片段 A?例如。 A->B->C -> "back" -> A 再比如:A->B> back -> A等?
  • 这正是我想要的。我以为我这样做是因为我只将片段 A 存储在后台堆栈中。我尝试了很多东西,但我放弃了,只有通过片段 A 导航到片段 b 和 c,但在 b 和 c 之间没有直接导航。如果我这样做,一切正常

标签: java android android-fragments


【解决方案1】:

实现你想要的最好方法是不使用片段的后台堆栈。

  1. 不要在任何地方使用addToBackStack()
  2. 在实例字段 mLoginFragment 中保留您的第一个片段 LoginFragment 引用。添加您的第一个片段将如下所示(可能在活动的onCreate()

      FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
      mLoginFragment = new LoginFragment();
      fragmentTransaction.replace(R.id.authentication_parent0_linear, mLoginFragment, LOGINTAG);
      fragmentTransaction.commit();
    
  3. 在您的活动中覆盖onBackPressed() 方法如下:

    @Override
    public void onBackPressed() {
        Fragment fr = getFragmentManager().findFragmentById(R.id.authentication_parent0_linear);
    
        // chek that mLoginFragment!=null, basically this should never happen! 
    
        if (fr == mLoginFragment) {
            super.onBackPressed();
        } else {
            FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
          fragmentTransaction.replace(R.id.authentication_parent0_linear, mLoginFragment, LOGINTAG);
          fragmentTransaction.commit();
        }
    }
    

有一种繁琐的方法可以通过使用 backstack 来达到预期的效果。方法如下:

  1. 不要在创建片段 A 时调用 addToBAckStack()
  2. 当从片段 A 导航到 B 或 C 或其他片段时调用 addToBackStack()
  3. 当从 B 到 C 等更深入地导航时,在事务之前调用 popBackStack()。可以在 SO 上找到它的解释。像这样:

    getFragmentManager().popBackStack();
    FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
      fragmentTransaction.replace(R.id.authentication_parent0_linear, new FragmentC(), "whatever");
      fragmentTransaction.addToBackStack(null);
      fragmentTransaction.commit();
    

【讨论】:

  • 谢谢 kirill 我会试试你的解决方案
【解决方案2】:

片段管理器允许您在给定状态上放置名称(或标签)。如果您将相同的名称传递给 popBackStack,它将弹出状态,直到达到该状态。例如

// Add initial fragment
getFragmentManager()
    .beginTransaction();
    .replace(R.id.authentication_parent0_linear, new LoginFragment());
    .addToBackStack(TAG_FIRST_FRAGMENT_STATE) // The key is not passing null here
    .commit();

// Add other fragments like such
getFragmentManager()
    .beginTransaction();
    .replace(R.id.authentication_parent0_linear, new SignupFragment());
    .addToBackStack(null)
    .commit();


// On back press
@Override
public void onBackPressed() {
    FragmentManager fragmentManager = getFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 1) {
        fragmentManager.popBackStack(TAG_FIRST_FRAGMENT_STATE, 0);
    } else {
        super.onBackPress();
    }
}

【讨论】:

  • 谢谢 cyroxis,我也试试这个
【解决方案3】:

我终于明白了。基于 Kirill K 的回答

    public class MainActivity extends Activity implements OnClickAuthentication,
    LoginInterface, SignupInterface {

FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    fragmentManager = getFragmentManager();
    Fragment fragment = fragmentManager.findFragmentByTag("one");
    if (fragment == null) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.relative, new OneFragment(), "one");
        fragmentTransaction.commit();
    }
}

@Override
public void onClickAuthButton(int flag) {
    if (flag == 2) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.relative, new TwoFragment(), "two");
        fragmentTransaction.commit();
    } else {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.relative, new ThreeFragment(),
                "three");
        fragmentTransaction.commit();

    }

}

@Override
public void switchToSignup() {
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction
            .replace(R.id.relative, new ThreeFragment(), "three");
    fragmentTransaction.commit();

}

@Override
public void switchToLogin() {
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.relative, new TwoFragment(), "two");
    fragmentTransaction.commit();

}

@Override
public void onBackPressed() {
    Fragment twoFragment = fragmentManager.findFragmentByTag("two");
    Fragment threeFragment = fragmentManager.findFragmentByTag("three");
    if ((twoFragment != null && twoFragment.isVisible())
            || (threeFragment != null && threeFragment.isVisible())) {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction
                .replace(R.id.relative, new OneFragment(), "one");
        fragmentTransaction.commit();
    } else {
        super.onBackPressed();
    }
}

}

【讨论】:

    【解决方案4】:

    我是这样做的

    1。全局声明 fragmentManager 变量:

    FragmentManager fm = getFragmentManager();
    

    2.onCreate 方法在不使用 backstack 的情况下加载您的第一个片段

    fm.beginTransaction().replace(R.id.content_frame , new main_fragment()).commit();

    3。现在,当您添加新片段时,然后创建一个方法来检查片段是否已经在后台堆栈中,并且它还将处理单击相同的片段事件(如果您在导航抽屉中使用片段)

    void replaceFragment (Fragment fragment) {
        Fragment current = fm.findFragmentById(R.id.content_frame);
        //Check if that frag is already opened
        if (!current.getClass().equals(fragment.getClass())) {
    
    
            String backStateName = fragment.getClass().getName();
    
            boolean fragmentPopped = fm.popBackStackImmediate(backStateName, 0);
    
            if (!fragmentPopped) {
    
                //fragment is not in back stack,so add it.
                FragmentTransaction ft = fm.beginTransaction();
                ft.replace(R.id.content_frame, fragment);
                ft.addToBackStack(backStateName);
                ft.commit();
    
            }
        }
        else {
            //if fragmentPopped is true then it will auto pop up the fragment
            //so we dnt have to do anything here     
        }
    }
    

    4。现在只需将您的片段类传递给

    replaceFragment(new yourfragment());

    5。现在处理回压

    public void onBackPressed() {
    
        int backStackEntryCount = fm.getBackStackEntryCount();
    
    
           if (backStackEntryCount == 0) {
                new AlertDialog.Builder(this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Closing Activity")
                        .setMessage("Are you sure you want to close this Application?")
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                                System.exit(0);
                            }
    
                        })
                        .setNegativeButton("No", null)
                        .setOnCancelListener(new DialogInterface.OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialogInterface) {
                                   //backpress over alert dialog
                                    finish();
                                    System.exit(0);
                            }
                        })
                        .show();
    
            } else {
    
    
                super.onBackPressed();
            }
    
    
        }
    

    希望对您有所帮助

    【讨论】:

      猜你喜欢
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      相关资源
      最近更新 更多