我的活动中有一些碎片

[1], [2], [3], [4], [5], [6]

如果当前活动片段是[2],那么在返回按钮上按下我必须从[2]返回到[1],否则什么也不做。

最好的做法是什么?

编辑:应用程序不能从[3]…[6]返回[2]


当前回答

或者你可以使用getSupportFragmentManager().getBackStackEntryCount()来检查要做什么:

@Override
    public void onBackPressed() {

        logger.d("@@@@@@ back stack entry count : " + getSupportFragmentManager().getBackStackEntryCount());

        if (getSupportFragmentManager().getBackStackEntryCount() != 0) {

            // only show dialog while there's back stack entry
            dialog.show(getSupportFragmentManager(), "ConfirmDialogFragment");

        } else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {

            // or just go back to main activity
            super.onBackPressed();
        }
    }

其他回答

如果您管理将每个事务添加到后退堆栈的流程,那么您可以这样做,以便在用户按后退按钮时显示上一个片段(您也可以映射home按钮)。

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

我认为最简单的方法是创建一个接口,并在Activity中检查片段是否属于接口类型,如果是,则调用它的方法来处理弹出。下面是要在片段中实现的接口。

public interface BackPressedFragment {

    // Note for this to work, name AND tag must be set anytime the fragment is added to back stack, e.g.
    // getActivity().getSupportFragmentManager().beginTransaction()
    //                .replace(R.id.fragment_container, MyFragment.newInstance(), "MY_FRAG_TAG")
    //                .addToBackStack("MY_FRAG_TAG")
    //                .commit();
    // This is really an override. Should call popBackStack itself.
    void onPopBackStack();
}

下面是如何实现它。

public class MyFragment extends Fragment implements BackPressedFragment
    @Override
    public void onPopBackStack() {
        /* Your code goes here, do anything you want. */
        getActivity().getSupportFragmentManager().popBackStack();
}

在你的Activity中,当你处理弹出时(可能在onBackPressed和onOptionsItemSelected中),使用这个方法弹出backstack:

public void popBackStack() {
    FragmentManager fm = getSupportFragmentManager();
    // Call current fragment's onPopBackStack if it has one.
    String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName();
    Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
    if (currentFragment instanceof BackPressedFragment)
        ((BackPressedFragment)currentFragment).onPopBackStack();
    else
        fm.popBackStack();
}

将addToBackStack()添加到片段事务中,然后使用下面的代码为片段实现反向导航

getSupportFragmentManager().addOnBackStackChangedListener(
    new FragmentManager.OnBackStackChangedListener() {
        public void onBackStackChanged() {
            // Update your UI here.
        }
    });

我正在与SlidingMenu和Fragment一起工作,在这里展示我的案例,希望能帮助到别人。

按[后退]键时的逻辑:

When SlidingMenu shows, close it, no more things to do. Or when 2nd(or more) Fragment showing, slide back to previous Fragment, and no more things to do. SlidingMenu not shows, current Fragment is #0, do the original [Back] key does. public class Main extends SherlockFragmentActivity { private SlidingMenu menu=null; Constants.VP=new ViewPager(this); //Some stuff... @Override public void onBackPressed() { if(menu.isMenuShowing()) { menu.showContent(true); //Close SlidingMenu when menu showing return; } else { int page=Constants.VP.getCurrentItem(); if(page>0) { Constants.VP.setCurrentItem(page-1, true); //Show previous fragment until Fragment#0 return; } else {super.onBackPressed();} //If SlidingMenu is not showing and current Fragment is #0, do the original [Back] key does. In my case is exit from APP } } }

创建接口:

后退按钮处理程序接口

public interface BackButtonHandlerInterface {
    void addBackClickListener (OnBackClickListener onBackClickListener);
    void removeBackClickListener (OnBackClickListener onBackClickListener);
}

OnBackClickListener

public interface OnBackClickListener {
     boolean onBackClick();
}

在活动:

public class MainActivity extends AppCompatActivity implements BackButtonHandlerInterface {

    private ArrayList<WeakReference<OnBackClickListener>> backClickListenersList = new ArrayList<>();

    @Override
    public void addBackClickListener(OnBackClickListener onBackClickListener) {
        backClickListenersList.add(new WeakReference<>(onBackClickListener));
    }

    @Override
    public void removeBackClickListener(OnBackClickListener onBackClickListener) {
        for (Iterator<WeakReference<OnBackClickListener>> iterator = backClickListenersList.iterator();
         iterator.hasNext();){
            WeakReference<OnBackClickListener> weakRef = iterator.next();
            if (weakRef.get() == onBackClickListener){
                iterator.remove();
            }
        }
    }

    @Override
    public void onBackPressed() {
        if(!fragmentsBackKeyIntercept()){
            super.onBackPressed();
        }
    }

    private boolean fragmentsBackKeyIntercept() {
        boolean isIntercept = false;
        for (WeakReference<OnBackClickListener> weakRef : backClickListenersList) {
            OnBackClickListener onBackClickListener = weakRef.get();
            if (onBackClickListener != null) {
                boolean isFragmIntercept = onBackClickListener.onBackClick();
                if (!isIntercept) isIntercept = isFragmIntercept;
            }
        }
        return isIntercept;
    }
}

在片段:

public class MyFragment extends Fragment implements OnBackClickListener{

    private BackButtonHandlerInterface backButtonHandler;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        backButtonHandler = (BackButtonHandlerInterface) activity;
        backButtonHandler.addBackClickListener(this);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        backButtonHandler.removeBackClickListener(this);
        backButtonHandler = null;
    }

    @Override
    public boolean onBackClick() {
        //This method handle onBackPressed()! return true or false
        return false;
    }

}

更新

提供自定义向后导航

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }

}