在返回按钮上的片段中,活动为空


73

我有一个活动,并且很多片段都膨胀了 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);

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


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


如果您来自主要活动,则按返回按钮,您期望得到什么?
伊万·斯科里克

我希望回到它,并真正看到它。由于FrameLayout仍然可见,我想使其不可见,但我不能在onBackPressed上切换,因为我将无法执行以下操作:活动>片段1>片段2> onBackPressed,它将直接进入活动并显示它,并跳过fragment2
Filip Luchianenco

只需将您的片段上的OnCreateView()覆盖方法更新为stackoverflow.com/a/53813425/1298105
bitsugar

Answers:


146

如果在活动中使用了多个片段,或者即使只有一个片段,则第一个片段不应定义addToBackStack。由于这允许向后导航,因此在此片段之前,将显示空的活动布局。

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

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


感谢您的回答! val sft = supportFragmentManager.beginTransaction() if (supportFragmentManager.fragments.isNotEmpty()) sft .addToBackStack(null) sft .commit()
Jose Pose S

浪费了很多时间,直到我看到你的答案!谢谢男人

43
@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();

23

回复晚了非常抱歉。

您不必添加 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

1
如果必须有此片段,则必须打开另一个片段。如果我们单击顶部的,将其关闭。
MSaudi 2014年

当我们创建一个带有片段作为登陆UI的Activity时非常有用。然后我们可以在需要时使用addToBackStack(null);添加所有其他片段。
Hardian

21

如果要按片段进行跟踪,则应覆盖该onBackPressed方法,如下所示

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

15

您可以覆盖onBackPressed并检查是否在堆栈上有任何东西。

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

1
我检查了该fragments值,即使它是第二个或第三个片段,也始终为0。
Filip Luchianenco


谢谢,但我仍然得到0。我getFragmentManager().executePendingTransactions();在每个片段之前都做过,我也尝试了第二种方法,before fm.getBackStackEntryCount()仍然没有运气。
Filip Luchianenco

5
请注意,如果使用supportedFragmentManager添加/替换片段,则还应该使用getSupportFragmentManager()。getBackStackEntryCount(),反之亦然
大卫,

3

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

这是为我工作的Kotlin代码。

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

2

在最近的个人项目中,我通过不调用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();
    }

1

如果要在第一个片段上按“后退”按钮时结束活动,则irscomp的解决方案有效。但是,如果您要跟踪所有片段,并按逆序从一个片段返回另一个片段,则可以添加所有片段,以便使用:

ft.addToBackStack(null);

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

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

总结:我不建议您使用此解决方案,因为如果您从fragment1转到fragment 2,反之亦然10次,则当您按10次返回按钮时,它将以相反的顺序进行操作,而用户将不希望这样做。


1

几乎与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);
}

1

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

为了解决这个问题,我刚刚finish()在我的onStop()方法中针对上述Activity进行了调用。像魅力一样工作。


1

我仍然无法解决问题getBackStackEntryCount(),我也通过将主页做成一个片段来解决了问题,所以最后我只有一个活动FrameLayout。以及包括主页在内的所有其他片段都将添加到该布局中。这解决了我的问题。


老实说,这听起来像是传统的设置。
JRomero

我不知道这是传统的,所以我重新发明了自行车。
Filip Luchianenco

但是我们如何将主页设置为片段
Mahesh 2014年

1.创建活动2.填充片段,然后在其中完成所有操作。查看此链接。stackoverflow.com/questions/5159982/...
菲利普Luchianenco
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.