【问题标题】:Skip some fragments onBackPressed跳过一些片段 onBackPressed
【发布时间】:2014-09-16 18:28:22
【问题描述】:

我对 android 片段还很陌生,所以请多多包涵。

我有一堆片段使用单个活动作为主机。

在我看来,我的片段是按部分分组的,尽管它们仍然是模块化/可按代码重用的。 考虑这种理想的情况:

Frag1 ->(按下一步)-> Frag2 ->(按下一步)-> Frag3 ->(按返回)-> Frag1

在浏览了一系列片段后,我想在按下后退按钮时跳过一些以前的片段(在这种情况下,跳过片段 2)。

但是,在我当前的代码中,我的问题是即使返回到 Frag1,Frag3 也不会从屏幕上消失。发生的情况是 Frag1 和 Frag3 都变得可见。

这是我的相关代码sn-ps:

用于创建 Frag1 的代码 sn-p

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    // init the fragment (with a default fragment, not null)
    Fragment fragment = PlaceholderFragment.newInstance(position + 1);
    // Position number from navigation sidebar starts from 0.
    // Since position starts from 0, add 1 to match section number
    // as implemented in {@link #onSectionAttached()}
    switch(position) {
        case 0:
            fragment = PlaceholderFragment.newInstance(position + 1);
            break;
        case 1: // Frag1 case
            fragment = new AddPointsFragment().newInstance(position + 1, "");
            break;
        default:
            break;
    }
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();
    // clear all fragments from previous section from the back stack
    fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    // replace all currently added fragments in container and replace with the new fragment
    fragmentManager.beginTransaction()
            .replace(R.id.container, fragment)
            .commit();
}

用于创建 Frag2 的代码 sn-p

public void onEnterButtonFragmentInteraction(int sectionNumber, String cardNo) {
    // TODO: Add point for given card number
    int points = 5; //sample points
    AddPointsSuccessFragment addPointsSuccessFragment =
            new AddPointsSuccessFragment().newInstance(sectionNumber, cardNo, points);
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.container, addPointsSuccessFragment)
            .addToBackStack(null)
            .commit();
}

用于创建 Frag3 的代码 sn-p

public void onOkButtonFragmentInteraction(int sectionNumber, String cardNo, int points) {
    RedeemRewardFragment redeemRewardFragment =
                new RedeemRewardFragment().newInstance(sectionNumber, cardNo, points);
        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container, redeemRewardFragment);
        fragmentTransaction.commit();
}

我目前的解决方法是在创建 Frag3 并运行此代码时添加 .addToBackStack(null)

public void onBackButtonFragmentInteraction() {
    this.onBackPressed(); // simulate pressing of activity back button
    FragmentManager fragmentmanager = getFragmentManager();
    fragmentmanager.popBackStack(); // pop Frag2 from back stack
}

在调用 onBackPressed() 方法之后。不幸的是,这种解决方法很难看,因为在转到 Frag1 之前,Frag2 会瞬间出现。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    所以你的解决方案的关键是这个人:

    .addToBackStack(null)
    

    您可以为该特定事务传入一个字符串标识符,而不是 null ——例如,我们使用 Fragment 的类名(尽管如果您有相同片段的多个实例,这将不起作用)后台):

    .addToBackStack(Fragment1.class.getName())
    

    然后,如果你想从Fragment3返回Fragment1,只需使用下一个片段的标识符弹出,并传递INCLUSIVE标志(这意味着它也会弹出你指定的下一个片段):

    getFragmentManager().popBackStack(
            Fragment2.class.getName(), 
            FragmentManager.POP_BACK_STACK_INCLUSIVE);
    

    这将按预期播放您的动画,但好像中间的片段从未存在过。我建议使用 next 片段的原因是因为您可能不希望您的第一个片段事务在后堆栈上。

    【讨论】:

    • 我尝试了您的建议,但不幸的是,屏幕仍然显示 Frag2 片刻,然后返回到 Frag1。我还为 Frag1 添加了代码 sn-p 以获得更好的视角。 :(
    • 经过进一步的实验,我发现在实施您的建议后,我不应该再调用 this.onBackPressed() 了。现在它起作用了“......好像中间的片段从未存在过。”谢谢! ;)
    • 我也遵循了同样的方法,但它对我不起作用,请在这里检查我做错了什么stackoverflow.com/questions/31118973
    • 如何通过按下导航返回按钮来移动 Frag3→Frag1?
    • 如果片段超过 3 个,则此方法无效。
    【解决方案2】:

    你可以试试这个,它应该可以工作并且不会产生瞬间延迟。虽然它的代码并不漂亮,如果有人有更好的方法,请发布。

    1.给你的片段一个标签。

    transaction.add(R.id.main_activity_container, FirstFragment, "FirstFragment");
    transaction.replace(R.id.main_activity_container, Second, "SECOND");
    transaction.replace(R.id.main_activity_container, Third, "THIRD");
    

    2.在“容纳”您的片段的 frameActivity(活动)中修改您的 onBackPressed()。

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
    
        int lastStack = getSupportFragmentManager().getBackStackEntryCount();
        try {
            //If the last fragment was named/tagged "three"
            if (getSupportFragmentManager().getFragments().get(lastStack).getTag().equalsIgnoreCase("THIRD")){
    
                getSupportFragmentManager().popBackStackImmediate();
                getSupportFragmentManager().popBackStackImmediate();
    
                //Get your first fragment that you loaded in the beginning. 
                Fragment first = getSupportFragmentManager().findFragmentByTag("FirstFragment");
                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                transaction.replace(R.id.main_activity_container, first);
                transaction.commit();
                return;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        super.onBackPressed();
    }
    

    【讨论】:

    • 出于对回答的赞赏,我尝试实施您的建议。虽然我花了一些时间来实施,但它确实有效!虽然我仍然更喜欢@kcoppock 的答案,因为它需要更少的代码更改和更少的混乱。不过,加分给你给我另一个可能的想法! :)
    • 是的,kcoppock 的答案在这种情况下可能是最好的,看起来更干净。也许我会在我的应用程序中更改为类似的解决方案:P。尽管它们的工作方式可能有所不同?如果你去,它的行为如何:Frag1 -> Frag2 -> Frag3 -> BackBtn 比 BackBtn 再次,它是退出还是你去 Frag2
    • 如果您的意思是 kcoppock 的建议,那么它会退出应用程序,因为它遵循了我想要的流程。 Frag1 -> 下一个 -> Frag2 -> 下一个 -> Frag3 -> 返回 -> Frag1 -> 返回 -> 退出
    【解决方案3】:

    当你显示 Frag2 时使用:

    final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.addToBackStack(FRAG_2);
    fragmentTransaction.replace(containerID, frag2, FRAG2_TAG);
    

    并在后按:

    @Override
    public void onBackPressed() {
       final Frag2 frag2 = (Frag2)getSupportFragmentManager().findFragmentByTag(FRAG2_TAG);
       if (frag2 != null && frag2.isVisible() && getSupportFragmentManager().getBackStackEntryCount() > 0) {
        getSupportFragmentManager().popBackStackImmediate();
        return;
       }
    }
    

    这将防止 frag2 在 onBackPressed() 调用后显示。 避免使用 popBackStack(),因为这会导致 frag2 生命周期触发(onCreate、onStart、onResume ...)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多