问题描述
想象一个包含3个片段的活动:开始显示第一个片段,选择一个菜单选项并转到第二个片段,选择另一个选项并转到第三个片段,然后再次选择第一个选项并返回第二个片段。
f1-> f2-> f3-> f2
当我按回时,我希望应用程序返回到片段3,当我再次按回时,它应该返回片段1,如果再次按回,则关闭应用程序。 类似于片段是否存在,将其移到堆栈顶部,如果不存在,则创建它。
谢谢!
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){
}
}
2楼
您可以在以下代码的帮助下实现此目的:
// 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.
}
});
在这里看看