当前位置: 代码迷 >> Android >> 碎片堆栈Android
  详细解决方案

碎片堆栈Android

热度:55   发布时间:2023-08-04 10:23:00.0

想象一个包含3个片段的活动:开始显示第一个片段,选择一个菜单选项并转到第二个片段,选择另一个选项并转到第三个片段,然后再次选择第一个选项并返回第二个片段。

f1-> f2-> f3-> f2

当我按回时,我希望应用程序返回到片段3,当我再次按回时,它应该返回片段1,如果再次按回,则关闭应用程序。 类似于片段是否存在,将其移到堆栈顶部,如果不存在,则创建它。

谢谢!

这是我随着时间推移提出的解决方案。 接下来的想法是,您需要保留一个堆栈数据结构,并且每当添加一个片段时也将其添加到堆栈中,然后重写onBackPress方法并检查堆栈是否不为空,然后使用堆栈顶部的新片段替换您的片段容器当它为空时,请执行super.onbackpress。这是所有基于片段的导航的父类。

public abstract class FragmentsStackActivity extends BaseActivity {
    public static final String TAG_BUNDLE = "bundle_tag";

    protected final Bundle fragmentArgs = new Bundle();
    protected Stack<Fragment> fragments = new Stack<>();

    abstract protected void setupFragments();

    public void setFragmentArguments(Fragment fragment, Bundle arguments){
        if(!fragments.isEmpty() && fragments.peek()!=fragment){
            fragment.setArguments(arguments);
        }
    }
    public void setFragmentFromStack() {
        if(!fragments.isEmpty()) {
            Fragment fragment = fragments.peek();
            final Fragment oldFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
            if (oldFragment == null || oldFragment != fragment) {
                getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                //transaction.setCustomAnimations(R.anim.animator_left_right_in, R.anim.animator_left_right_in);
                transaction.replace(R.id.fragment_container, fragment).commit();
            }
        }else {
            finish();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        //TODO need to save fragment stack
    }
}

扩展此类的活动的示例

public class LoginActivity extends FragmentsStackActivity{

    private final MyFragment1 fragment1 = new MyFragment1();
    private final MyFragment2 fragment2 = new MyFragment2();

    private final User mUser = new User();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        setupFragments();
        setFragmentFromStack();
    }


    @Override
    protected void setupFragments() {
        fragments.add(fragment2);
        //fragment2.setNotifier(this); // I use notifiers listener but you can choose whatever convenient for you
        Bundle fragmentArgs = new Bundle();
        fragmentArgs.putBoolean(Constants.TAG_LOGIN, true);
        fragmentArgs.putParcelable(User.TAG, mUser);
        fragmentArgs.putInt(Constants.TYPE, getIntent().getIntExtra(Constants.TYPE, 0));
        fragment2.setArguments(fragmentArgs);
        //fragment1.setNotifier(this); // I use notifiers listener but you can choose whatever convenient for you
    }


    // this method teals with handling messages from fragments in order to provide navigation 
    // when some actions taken inside the fragment, you can implement your own version 
    public void onReceiveMessage(String tag, Bundle bundle) {
        switch (tag) {
            case MyFragment2.TAG_BACK:
            case MyFragment1.TAG_BACK:
                fragments.pop();
                setFragmentFromStack();
                break;
            case MyFragment2.TAG_NEXT:
                fragment1.setArguments(bundle);
                fragments.add(fragment1);
                setFragmentFromStack();
                break;
            case MyFragment1.TAG_NEXT:
                goToWelcomeScreen(bundle);
                finish();
                break;
        }
    }

    private void goToWelcomeScreen(Bundle bundle){

    }
}

您可以在以下代码的帮助下实现此目的:

// transaction.replace(R.id.detailFragment, frag1);
Transaction.remove(null).add(frag1)  // frag1 on view

// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);
Transaction.remove(frag1).add(frag2).addToBackStack(null)  // frag2 on view

// transaction.replace(R.id.detailFragment, frag3);
Transaction.remove(frag2).add(frag3)  // frag3 on view

为了更好地理解,请阅读以下代码段:

// Works with either the framework FragmentManager or the
// support package FragmentManager (getSupportFragmentManager).
getSupportFragmentManager().beginTransaction()
                       .add(detailFragment, "detail")
                       // Add this transaction to the back stack
                       .addToBackStack()
                       .commit();



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

在这里看看

  相关解决方案