简体   繁体   English

Android:在背面按下返回上一个片段

[英]Android : Return to previous fragment on back press

I have implemented Navigation Drawer which is a subclass of Activity. 我已经实现了Navigation Drawer,它是Activity的子类。 I have many fragments in my application. 我的应用程序中有很多片段。 My question goes here 我的问题在这里

Imagine there are 3 fragments : 想象一下有3个片段:

Fragment_1 : Fragment_2 : Fragment_3 Fragment_1:Fragment_2:Fragment_3

When I start my application, Fragment_1 is loaded When I click on some components on Fragment_1, I'm navigated to Fragment_2 and so on.. 当我启动我的应用程序时,Fragment_1被加载当我点击Fragment_1上的一些组件时,我将导航到Fragment_2,依此类推。

So it's like 所以它就像

Fragment_1 > Fragment_2 > Fragment_3 Fragment_1> Fragment_2> Fragment_3

When I press back key from Fragment_2, I'm navigated back to Fragment_1 But when I press back key from Fragment_3, I'm navigated back to Fragment_1 (instead of Fragment_2) 当我从Fragment_2按回键时,我被导航回Fragment_1但是当我从Fragment_3按回键时,我被导航回Fragment_1(而不是Fragment_2)

I want something like this in my application on Back Key press 我在Back Key按下的应用程序中想要这样的东西

Fragment_1 < Fragment_2 < Fragment_3 Fragment_1 <Fragment_2 <Fragment_3

I have used Fragment, FragmentManager, FragmentTransaction as follows : 我使用Fragment,FragmentManager,FragmentTransaction如下:

MyFragment fragment = new MyFragment();
FragmentManager fragmentManager = getFragmentManager();

fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null)commit();

and I tried overriding onBackPressed() in my MainActivity : 我尝试在我的MainActivity中覆盖onBackPressed():

@Override
public void onBackPressed() {


        getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        int count = getFragmentManager().getBackStackEntryCount();
        if (count == 0)
               super.onBackPressed();
    }

Update your Activity#onBackPressed() method to: Activity#onBackPressed()方法更新为:

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

The reason your implementation doesn't work is because the method FragmentManager#popBackStack() is asynchronous and does not happen right after it is called. 你的实现不起作用的原因是因为FragmentManager#popBackStack()是异步的,并且在调用之后不会发生。

From the documentation: 从文档:

This function is asynchronous -- it enqueues the request to pop, but the action will not be performed until the application returns to its event loop. 此函数是异步的 - 它将请求排入pop,但在应用程序返回其事件循环之前不会执行该操作。

Reference: http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack(java.lang.String,%20int) 参考: http//developer.android.com/reference/android/app/FragmentManager.html#popBackStack(java.lang.String,%20int)

You have to implement your own backstack implementation as explained here 您必须按照此处的说明实现自己的backstack实现

Separate Back Stack for each tab in Android using Fragments 使用Fragments为Android中的每个选项卡分隔Back Stack

You can call the popFragments() whenever you click the back button in a fragment and call pushFragments() whenever you navigate from one Fragment to other. 只要单击片段中的后退按钮,就可以调用popFragments(),只要从一个片段导航到另一个片段,就可以调用pushFragments()。

in Short, 简而言之,

public void onBackPressed()
{
    FragmentManager fm = getActivity().getSupportFragmentManager();
    fm.popBackStack();
}

The tric is in FragmentManager#executePendingTransactions(); FragmentManager#executePendingTransactions();FragmentManager#executePendingTransactions(); .

This is what I use for nested fragments as well...: 这也是我用于嵌套片段的原因......:

/**
 * if there is a fragment and the back stack of this fragment is not empty,
 * then emulate 'onBackPressed' behaviour, because in default, it is not working.
 *
 * @param fm the fragment manager to which we will try to dispatch the back pressed event.
 * @return {@code true} if the onBackPressed event was consumed by a child fragment, otherwise
 */
public static boolean dispatchOnBackPressedToFragments(FragmentManager fm) {

    List<Fragment> fragments = fm.getFragments();
    boolean result;
    if (fragments != null && !fragments.isEmpty()) {
        for (Fragment frag : fragments) {
            if (frag != null && frag.isAdded() && frag.getChildFragmentManager() != null) {
                // go to the next level of child fragments.
                result = dispatchOnBackPressedToFragments(frag.getChildFragmentManager());
                if (result) return true;
            }
        }
    }

    // if the back stack is not empty then we pop the last transaction.
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
        fm.executePendingTransactions();
        return true;
    }

    return false;
}

and in my onBackPressed : 在我的onBackPressed

                if (!FragmentUtils.dispatchOnBackPressedToFragments(fm)) {
                    // if no child fragment consumed the onBackPressed event,
                    // we execute the default behaviour.
                    super.onBackPressed();
                }

Use this code on tab change in your main activity to clear the stack. 在主活动中更改选项卡上使用此代码以清除堆栈。

int count = getFragmentManager().getBackStackEntryCount();
        if(count>0){
            for (int i = 0; i <count; i++) {
                getFragmentManager().popBackStack();
            }
        }

Then on Back pressed of your main activity do this 然后在你的主要活动的背面按下这样做

 int count = getFragmentManager().getBackStackEntryCount();

     if (count == 0) {
         super.onbackpressed();
        }
else {
        getFragmentManager().popBackStack();
    }
 }

Here is working and tested code by me, This will help you 这是我的工作和测试代码,这将对您有所帮助

 private static final int TIME_INTERVAL = 2000;
private long mBackPressed;
 private void applyExit() {
    if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
        finish();
    } else {
         Toast.makeText(this,"Press Again to exit",Toast.LENGTH_LONG).show();
    }
    mBackPressed = System.currentTimeMillis();
}

@Override
public void onBackPressed() {
    fm = getSupportFragmentManager();
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    }
    if (fm.getFragments().size() <= 1) {
        applyExit();
    } else {
        for (Fragment frag : fm.getFragments()) {
            if (frag == null) {
                applyExit();
                return;
            }
            if (frag.isVisible()) {
                FragmentManager childFm = frag.getChildFragmentManager();
                if (childFm.getFragments() == null) {
                    super.onBackPressed();
                    return;
                }
                if (childFm.getBackStackEntryCount() > 0) {
                    childFm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    return;
                } else {
                    fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    return;
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM