【问题标题】:In Fragment on back button pressed Activity is blank在按下后退按钮的片段中,活动为空白
【发布时间】:2020-01-07 04:48:43
【问题描述】:

我有一个 Activity 和许多片段在同一个 FrameLayout 中膨胀

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

示例:mainActivity > 任何片段(按返回按​​钮)> 活动为空白。

在 onCreate 中:

layout = (FrameLayout)findViewById(R.id.content_frame);
layout.setVisibility(View.GONE);

当我开始一个片段时:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, profileFragment);
ft.addToBackStack(null);
ft.commit();
layout.setVisibility(View.VISIBLE);

我想我需要在按下后再次使 frameLayout 的可见性 GONE,但我该怎么做呢?


我尝试了onBackPressed 并设置了layout.setVisibility(View.GONE);,但我无法返回片段,因为我直接进入了主页。

【问题讨论】:

  • 如果你来自主要活动,那么你按下后退按钮,你期望得到什么?
  • 我希望回到它,并真正看到它。由于FrameLayout 仍然可见,我想让它不可见,但我不能覆盖 onBackPressed,因为我无法像这样:activity > fragment1 > fragment2 > onBackPressed 它将直接进入活动并显示它,并且跳过片段2
  • 只需将片段上的 OnCreateView() 覆盖方法更新为 stackoverflow.com/a/53813425/1298105

标签: android android-fragments


【解决方案1】:

如果您在活动中使用了多个片段,或者即使您只有一个片段,那么第一个片段不应该定义 addToBackStack。由于这允许返回导航,并且在此片段之前将显示空的活动布局。

 // fragmentTransaction.addToBackStack() // dont include this for your first fragment.

但是对于其他片段,您需要定义它,否则后面将不会导航到较早的屏幕(片段),而是应用程序可能会关闭。

【讨论】:

  • 感谢您的回答!! val sft = supportFragmentManager.beginTransaction() if (supportFragmentManager.fragments.isNotEmpty()) sft .addToBackStack(null) sft .commit()
  • 在我看到你的答案之前浪费了这么多时间!谢谢人
  • 谢谢。它节省了很多调试时间
【解决方案2】:
@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    }
    else {
        int fragments = getSupportFragmentManager().getBackStackEntryCount();
        if (fragments == 1) {
            finish();
        } else if (getFragmentManager().getBackStackEntryCount() > 1) {
            getFragmentManager().popBackStack();
        } else {
            super.onBackPressed();
        }
    }
}

添加片段

 getSupportFragmentManager().beginTransaction()
                .replace(R.id.layout_main, dashboardFragment, getString(R.string.title_dashboard))
                .addToBackStack(getString(R.string.title_dashboard))
                .commit();

【讨论】:

    【解决方案3】:

    抱歉回复晚了。

    您不必在添加第一个片段时添加 ft.addToBackStack(null);

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.content_frame, profileFragment);
    // ft.addToBackStack(null); --remove this line.
    ft.commit();
    // ... rest of code
    

    【讨论】:

    • 如果我们有这个片段,我们必须打开另一个片段。如果我们点击顶部的返回,它将关闭它。
    • 非常有用,当我们创建一个带有片段作为登陆UI的Activity时。然后我们可以在需要时使用 addToBackStack(null); 添加所有其他片段。
    【解决方案4】:

    如果你想通过片段进行跟踪,你应该重写 onBackPressed 方法,像这样

    public void onBackPressed() { 
       if (getFragmentManager().getBackStackEntryCount() == 1) {
            finish();
       } else {
            super.onBackPressed();
       }
    }
    

    【讨论】:

      【解决方案5】:

      您可以覆盖onBackPressed 并检查后台堆栈是否有任何内容。

      @Override
      public void onBackPressed() {
          int fragments = getFragmentManager().getBackStackEntryCount();
          if (fragments == 1) { 
              // make layout invisible since last fragment will be removed
          }
          super.onBackPressed();
      }
      

      【讨论】:

      • 我检查了fragments的值,它总是0,即使它是第二个或第三个片段。
      • 谢谢,但我仍然得到 0。我在每个片段之前都做了getFragmentManager().executePendingTransactions();,我也尝试了第二种方法,before fm.getBackStackEntryCount(),但仍然没有运气。
      • 请注意,如果您使用supportedFragmentManager添加/替换片段,您还应该使用getSupportFragmentManager().getBackStackEntryCount(),反之亦然
      【解决方案6】:

      只是不要将第一个片段添加到后台堆栈

      这是对我有用的 Kotlin 代码。

          val ft = supportFragmentManager.beginTransaction().replace(container, frag)
          if (!supportFragmentManager.fragments.isEmpty()) ft.addToBackStack(null)
          ft.commit()
      

      【讨论】:

        【解决方案7】:

        在最近的一个个人项目中,如果堆栈为空,我通过不调用 addToBackStack 解决了这个问题。

            // don't add the first fragment to the backstack
            // otherwise, pressing back on that fragment will result in a blank screen
            if (fragmentManager.getFragments() != null) {
                transaction.addToBackStack(tag);
            }
        

        这是我的完整实现:​​

            String tag = String.valueOf(mCurrentSectionId);
            FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
            Fragment fragment = fragmentManager.findFragmentByTag(tag);
        
            if (fragment != null) {
                // if the fragment exists then no need to create it, just pop back to it so
                // that repeatedly toggling between fragments doesn't create a giant stack
                fragmentManager.popBackStackImmediate(tag, 0);
            } else {
                // at this point, popping back to that fragment didn't happen
                // So create a new one and then show it
                fragment = createFragmentForSection(mCurrentSectionId);
        
                FragmentTransaction transaction = fragmentManager.beginTransaction()
                        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                        .replace(R.id.main_content, fragment, tag);
        
                // don't add the first fragment to the backstack
                // otherwise, pressing back on that fragment will result in a blank screen
                if (fragmentManager.getFragments() != null) {
                    transaction.addToBackStack(tag);
                }
        
                transaction.commit();
            }
        

        【讨论】:

          【解决方案8】:

          如果您想在第一个片段上按下后退按钮时结束活动,则 irscomp 的解决方案有效。但是,如果您想跟踪所有片段,并按顺序从一个返回到另一个片段,则将所有片段添加到堆栈中:

          ft.addToBackStack(null);
          

          然后,将其添加到 onCreate() 的末尾以避免最后一次按下时出现空白屏幕;您可以根据您的 API 使用 getSupportFragmentManager() 或 getFragmentManager():

          FragmentManager fm = getSupportFragmentManager();
              fm.addOnBackStackChangedListener(new OnBackStackChangedListener() {
                  @Override
                  public void onBackStackChanged() {
                      if(getSupportFragmentManager().getBackStackEntryCount() == 0) finish();             
                  }
          });
          

          最后的话:我不建议你使用这个解决方案,因为如果你从片段 1 到片段 2,反之亦然 10 次,当你按下后退按钮 10 次时,它会按顺序执行,用户不会想要。

          【讨论】:

            【解决方案9】:

            Goodlife的回答几乎相同,但采用Xamarin.Android方式:

            加载片段(我为此编写了辅助方法,但这不是必需的):

            public void LoadFragment(Activity activity, Fragment fragment, string fragmentTitle = "")
            {
                var fragmentManager = activity.FragmentManager;
                var fragmentTransaction = fragmentManager.BeginTransaction();
            
                fragmentTransaction.Replace(Resource.Id.mainContainer, fragment);
                fragmentTransaction.AddToBackStack(fragmentTitle);
            
                fragmentTransaction.Commit();
            }
            

            返回按钮(MainActivity):

            public override void OnBackPressed()
            {
                if (isNavDrawerOpen()) drawerLayout.CloseDrawers();
                else
                {
                    var backStackEntryCount = FragmentManager.BackStackEntryCount;
            
                    if (backStackEntryCount == 1) Finish();
                    else if (backStackEntryCount > 1) FragmentManager.PopBackStack();
                    else base.OnBackPressed();
                }
            }
            

            还有isNavDrawerOpen方法:

            bool isNavDrawerOpen()
            {
                return drawerLayout != null && drawerLayout.IsDrawerOpen(Android.Support.V4.View.GravityCompat.Start);
            }
            

            【讨论】:

              【解决方案10】:

              我仍然无法通过getBackStackEntryCount() 解决问题,我也通过将主页设为片段解决了我的问题,所以最后我只有FrameLayout 的活动;以及所有其他片段,包括我膨胀到该布局中的主页。这解决了我的问题。

              【讨论】:

              • 老实说,这听起来像是传统设置。
              • 我不知道这是传统的,所以我重新发明了自行车。
              • 但是我们如何将主页设置为片段
              • 1.创建活动 2。膨胀片段并在那里做所有的事情。看看这个链接。 stackoverflow.com/questions/5159982/…
              【解决方案11】:

              在处理 Firebase 的 Ui 登录屏幕时,我遇到了同样的问题。当按下返回按钮时,它会留下一个空白屏幕。

              为了解决我刚刚在我的onStop() 方法中为所述活动调用finish() 的问题。像魅力一样工作。

              【讨论】:

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