从堆栈中弹出多个片段

时间:2018-01-05 16:48:39

标签: android android-fragments xamarin.android mvvmcross

我正在使用Xamarin.Android和MvvmCross编写应用程序,但这个问题一般适用于原生Android。我希望能够声明一个根片段,以便以后可以在堆栈上弹出它上面的所有片段。例如,如果我有片段:

A | B | C | d

我目前正处于片段D,我希望能够立即弹出片段B,C和D以回到片段A.我试图在我看来使用CurrentFragmentManager.PopBackStack方法执行此操作主持人,但它没有像我期望的那样工作。这是我的实施:

public class ViewPresenter : MvxAppCompatViewPresenter
{
    private int _rootFragmentId;
    private int _currentFragmentId;

    public ViewPresenter(IEnumerable<Assembly> androidViewAssemblies) : base(androidViewAssemblies)
    {
        AddPresentationHintHandler<SetRootHint>(SetRootHintHandler);
        AddPresentationHintHandler<PopToRootHint>(PopToRootHintHandler);
    }

    protected override void ShowFragment(Type view, MvxFragmentPresentationAttribute attribute, MvxViewModelRequest request)
    {
        base.ShowFragment(view, attribute, request);

        // Keep track of the ID of the current fragment (the ID that is given in the Resource)
        _currentFragmentId = attribute.FragmentContentId;
    }

    private bool SetRootHintHandler(SetRootHint hint)
    {
        _rootFragmentId = _currentFragmentId;

        return true;
    }

    private bool PopToRootHintHandler(PopToRootHint hint)
    {
        // This doesn't do anything
        CurrentFragmentManager.PopBackStack(_rootFragmentId, 0);

        return true;
    }
}

修改

Subrato M.的想法对我有用。这是Xamarin开发人员的C#实现:

public class ViewPresenter : MvxAppCompatViewPresenter
{
    private string _rootFragmentName;
    private string _currentFragmentName;

    public ViewPresenter(IEnumerable<Assembly> androidViewAssemblies) : base(androidViewAssemblies)
    {
        AddPresentationHintHandler<SetRootHint>(SetRootHintHandler);
        AddPresentationHintHandler<PopToRootHint>(PopToRootHintHandler);
    }

    protected override void ShowFragment(Type view, MvxFragmentPresentationAttribute attribute, MvxViewModelRequest request)
    {
        base.ShowFragment(view, attribute, request);

        _currentFragmentName = view.FullName;
    }

    private bool SetRootHintHandler(SetRootHint hint)
    {
        _rootFragmentName = _currentFragmentName;

        return true;
    }

    private bool PopToRootHintHandler(PopToRootHint hint)
    {
        while (CurrentFragmentManager.BackStackEntryCount > 0 &&
               CurrentFragmentManager.GetBackStackEntryAt(CurrentFragmentManager.BackStackEntryCount-1).Name.ToLowerInvariant() != _rootFragmentName.ToLowerInvariant())
        {
            CurrentFragmentManager.PopBackStackImmediate();
        }

        return true;
    }
}

1 个答案:

答案 0 :(得分:1)

您可以递归地从BackStackChangedListener调用popBackStack,直到找到所需的片段:

boolean isBackStackListenerAdded = false;

public void popFragments() {
    if (getFragmentManager().getBackStackEntryCount() > 0) {
        getFragmentManager().popBackStack();
        if(!isBackStackListenerAdded) {
            isBackStackListenerAdded = true;
            getFragmentManager().addOnBackStackChangedListener(listener);
        }
    }
}

FragmentManager.OnBackStackChangedListener listener = new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        String fragmentTag = getFragmentManager().getBackStackEntryAt(getFragmentManager().getBackStackEntryCount() - 1).getName();
        Fragment currentBackStackFragment = getFragmentManager().findFragmentByTag(fragmentTag);
        if(currentBackStackFragment instanceof AFragment) {
            if(isBackStackListenerAdded) {
                getFragmentManager().removeOnBackStackChangedListener(this);
                isBackStackListenerAdded = false;
            }
        } else {
            popFragments();
        }
    }
};