Android 导航抽屉,处理后退按钮去上一个片段?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21093287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:58:36  来源:igfitidea点击:

Navigation drawer, handling the back button to go to previous fragments?

androidandroid-fragmentsandroid-fragmentactivitynavigation-drawer

提问by RED_

I'm using the built in navigation drawer to run my app. I can't quite figure out how to handle the back button. When it's pressed I want it to load the very first fragment again. Fragment1.

我正在使用内置的导航抽屉来运行我的应用程序。我不太明白如何处理后退按钮。当它被按下时,我希望它再次加载第一个片段。片段1。

So when the app launches you see Fragment1 launched. They can then click on Fragment 2-5 to go to other pages. Within all of these pages I want the back button to take the user back to Fragment1. The only place the user should be able to exit the app via the back button is Fragment1.

因此,当应用程序启动时,您会看到 Fragment1 已启动。然后他们可以单击 Fragment 2-5 转到其他页面。在所有这些页面中,我希望后退按钮将用户带回 Fragment1。用户应该能够通过后退按钮退出应用程序的唯一地方是 Fragment1。

SInce it's all handled by a FragmentActivity I tried messing with the backbutton there. I keep getting a force close error however:

因为这一切都是由 FragmentActivity 处理的,所以我尝试弄乱那里的后退按钮。但是,我不断收到强制关闭错误:

(01-11 14:09:33.114: E/AndroidRuntime(8292): android.view.InflateException: Binary XML file line #7: Error inflating class fragment)

This is what I have so far:

这是我到目前为止:

I've made sure to add the fragments to the back stack like this:

我确保像这样将片段添加到后堆栈中:

fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();

Back button:

返回键:

@Override
public void onBackPressed() {
    if (getSupportFragmentManager().findFragmentByTag("fragBack") != null) {

    }
    else {
        super.onBackPressed();
        return;
    }
    if (getSupportFragmentManager().getBackStackEntryCount() != 0) {
        Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_LONG).show();
        Fragment frag = getSupportFragmentManager().findFragmentByTag("fragBack");
        FragmentTransaction transac = getSupportFragmentManager().beginTransaction().remove(frag);
                transac.commit();
    }

}

Does anyone know what I need to do? Do I need to call onBackPressed in every fragment (if that's even possible) rather than the FragmentActivity that controls the drawer? In my past apps I've been OK with the back button closing the app regardless of which Fragment the user is on but the one I'm making now I want the back button to go back to Fragment1.

有谁知道我需要做什么?我是否需要在每个片段中调用 onBackPressed (如果可能的话)而不是控制抽屉的 FragmentActivity ?在我过去的应用程序中,无论用户在哪个 Fragment 上,我都可以通过后退按钮关闭应用程序,但我现在正在制作的那个我希望后退按钮返回到 Fragment1。

Would really appreciate some help, thank you.

真的很感激一些帮助,谢谢。

onItemClick

项目点击

@Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

            Fragment newFragment = new MapsPage();
            FragmentManager fm = getSupportFragmentManager();
            switch(i) {
            case 0:
                newFragment = new Fragment2();
                break;
            case 1:
                newFragment = new Fragment3();
                break;
            case 2:
                newFragment = new Fragment4();
                break;
            case 3:
                newFragment = new Fragment5();
                break;
            }
            fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragback").commit();
            drawerLayout.closeDrawer(rl);
        }

回答by vipul mittal

Instead of:

代替:

fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();

Call:

称呼:

fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();

addToBackStack works with add.

addToBackStack 与add.

replacefunction removes previous fragment and places new fragment so on your back-stack there is only one fragment all the time. So use add function to keep previous fragments on stack.

replace函数删除前一个片段并放置新片段,因此在您的后台堆栈中始终只有一个片段。因此,使用 add 函数将先前的片段保留在堆栈中。

To always goto fragemnt1 from any fragment onBackPress try to do following:

要始终从 onBackPress 的任何片段转到 fragemnt1,请尝试执行以下操作:

getFragmentManager().popBackStack();
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();

this will remove last transaction from backstack and add new one. Try this.

这将从 backstack 中删除最后一个事务并添加新的事务。尝试这个。

回答by Kyle

Just wanted to report my findings even though this question is a little old for anyone else who may have had the same problem with the accepted answer. For me, doing the method suggested in the accepted answer, made the layers overlap, quickly making them unreadable. The code below (adapted from the accepted answer) avoids the overlaying but still adds the screen to the back stack.

只是想报告我的发现,即使这个问题对于其他可能对接受的答案有同样问题的人来说有点老了。对我来说,按照已接受的答案中建议的方法,使图层重叠,很快使它们变得不可读。下面的代码(改编自已接受的答案)避免了覆盖,但仍将屏幕添加到后堆栈。

fragmentManager.beginTransaction().replace(R.id.container, fragment).addToBackStack("fragBack").commit();

Hope this helps someone!

希望这可以帮助某人!

回答by Muzhan

in some cases you have to use replace then you cant work with addtobackstack() so you can use this code in mainActivity. in this code when you press back key you always go to first Fragment( i call it HomeFragment ) and when you are in Home Fragment it ask twice time to go out from application (sorry for my poor English)

在某些情况下,您必须使用替换,然后您就无法使用 addtobackstack(),因此您可以在 mainActivity 中使用此代码。在这段代码中,当您按下返回键时,您总是会转到第一个 Fragment(我称之为 HomeFragment),而当您在 Home Fragment 中时,它会询问两次退出应用程序的时间(对不起,我的英语不好)

 private Boolean exit = false;
@Override
    public void onBackPressed() {
        if (exit) {
            super.onBackPressed();
            return;
        }

    try {
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag("HOME");
        if (fragment != null) {
            if (fragment.isVisible()) {
                this.exit = true;
                Toast.makeText(this, "Press Back again to Exit", Toast.LENGTH_SHORT).show();
            }
        }
        else {
            fragment = HomeFragment.class.newInstance();
            getFragmentManager().popBackStack();
            fragmentManager.beginTransaction().replace(R.id.flContent, fragment, "HOME").commit();
        }
    } catch (Exception e) {

    }
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            exit = false;
        }
    }, 2000);
}

回答by Neeraj Gupta

 - @Override
       public void onBackPressed() {
           DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
           int backstack = getSupportFragmentManager().getBackStackEntryCount();
           if (drawer.isDrawerOpen(GravityCompat.START)) {
               drawer.closeDrawer(GravityCompat.START);
           } else if (backstack > 0) {
              for (int i = 0; i < backstack; i++) {
                   getSupportFragmentManager().popBackStackImmediate();
            }
       } else {
           this.finish();
        }
    }

回答by Matthew Cordaro

I would suggest avoiding an override of onBackPressed()altogether by managing your transactions properly in the first place. This will help to avoid having to implement crazy logic down the road.

我建议onBackPressed()首先通过正确管理您的交易来避免完全覆盖。这将有助于避免在未来实施疯狂的逻辑。

To do this first we need to set a private class variable in that will enable initialization:

首先,我们需要设置一个私有类变量,以启用初始化:

private boolean popNext = false;

The following code allows us to setup the initial back function by placing it on the stack. Every time thereafter, when popNextis set to true, we pop the initial transaction and push the new one. So we are replacing the 1>Xtransaction with the 1>Ytransaction.

下面的代码允许我们通过将它放在堆栈上来设置初始返回函数。此后每次popNext设置为 true 时,我们都会弹出初始交易并推送新交易。因此,我们要更换1> X与交易1>ÿ交易。

The extra embedded ifstatements deal with selecting the initial item, since we don't want to go from 1>1. If it's our initial case we just close the drawer. The other case needs to act like the back button, but we need to remember to set it as if it is returning to the initial state!

额外的嵌入if语句处理选择初始项,因为我们不想从1>1 开始。如果这是我们的初始案例,我们只需关闭抽屉。另一种情况需要像后退按钮一样起作用,但我们需要记住将其设置为好像返回初始状态!

if(popNext){
    if(i == INITIAL_POSITION){
        onBackPressed();
        mDrawerLayout.closeDrawer(mDrawerList);
        popNext = false;
        return;
    }
    getFragmentManager().popBackStackImmediate();
}
else{
    if(i == INITIAL_POSITION){
        mDrawerLayout.closeDrawer(mDrawerList);
        return;
    }
    popNext=true;
}
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();

Note:My code uses getFragmentManager()instead of getSupportFragmentManager()which is a native function, I believe as of Honeycomb.

注意:我的代码使用getFragmentManager()getSupportFragmentManager()是本机函数而不是它,我相信从 Honeycomb 开始。