片段行为异常使用addToBackStack当() [英] Fragments Behave Weirdly When Using addToBackStack()

查看:153
本文介绍了片段行为异常使用addToBackStack当()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有关此问题的SSCCE是可以在GitHub上

有关未来的读者,原来的例子就是在同一个项目的分支。

这SSCCE有ListView和一排按钮。这些按钮都应该改变在ListView中的数据,并在ListView行(点击时)都应该打开一个新的片段,推进backstack而住在同一个活动。

如果做以下事情,它会产生以下结果:

  1. 打开应用程序。
  2. 点击ListView控件。 - FragmentTransaction.replace(...) addToBackStack(真)
  3. 点击任何按钮。 - FragmentTransaction.replace(...) addToBackStack(假)
  4. 点击返回按钮。

结果:

两个片段可见,但我只希望第一个加载的片段(ListTwoFragment <$ C C $>在code)来显示。请问这是怎么片段应该工作?如果是这样,我怎么能得到预期的效果?

MainActivity.java:

 公共类MainActivity扩展FragmentActivity实现ListTwoFragment.Callbacks,
    ListThreeFragment.Callbacks {
    公共静态最后弦乐KEY_ARGS =ARGS;

    私人字符串curUri =;
    私人字符串curArgs =;

    @覆盖
    保护无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);

        selectContent(假);
    }

    私人无效selectContent(布尔addToBackStack){
        片段片段

        如果(curUri.isEmpty()){
            //使用默认片段
            片段=新ListTwoFragment();
            curUri = ListTwoFragment.class.getName();
        }
        其他 {
            尝试 {
                类&LT;片断&gt; fragmentClass =(类&LT;片断&gt;)的Class.forName(curUri);
                片段= fragmentClass.newInstance();
            }
            赶上(例外五){// ClassNotFound的,IllegalAccess等。
                返回;
            }
        }

        //配置片段
        捆绑的args =新包();
        args.putString(KEY_ARGS,curArgs);
        fragment.setArguments(参数);

        attachFragment(片段,addToBackStack,curUri +;+ curArgs,R.id.fragment_container);
    }

    保护无效attachFragment(片段片段,布尔addToBackStack,字符串变量,INT replaceId){
        FragmentTransaction交易= getSupportFragmentManager()的BeginTransaction()。
        transaction.replace(replaceId,片段,标记);
        如果(addToBackStack)transaction.addToBackStack(标签);
        器transaction.commit();
    }

    @覆盖
    公共无效onTwoButtonClick(字符串名称){
        curUri = ListTwoFragment.class.getName();
        curArgs =称号;
        selectContent(假);
    }

    @覆盖
    公共无效onTwoListClick(){
        curUri = ListThreeFragment.class.getName();
        curArgs =;
        selectContent(真正的);
    }

    @覆盖
    公共无效onThreeButtonClick(字符串名称){
        curUri = ListThreeFragment.class.getName();
        curArgs =称号;
        selectContent(假);
    }
}
 

解决方案

我正与片段,而我做的方式: 前进(添加到栈),和backwords(从堆栈中删除)是两个不同的功能

添加到协议栈和改变片段:

 公共无效changeFragmentAddToStack(片段myNewFragment){
        FragmentTransaction T = getSupportFragmentManager()的BeginTransaction()。
        t.add(R.id.main_fragment,myNewFragment);
        t.addToBackStack(空);
        t.commit();
    }
 

要回到堆栈:

 公共无效goBackStackMain(){
    FragmentManager人= getSupportFragmentManager();

                如果(man.getBackStackEntryCount()大于0){
                    man.popBackStack(man.getBackStackEntryAt(0).getName(),FragmentManager.POP_BACK_STACK_INCLUSIVE);
            }
}
 

如果你想做到既:要返回堆栈并更改片段:

 公共无效goBackStackAndReplaceFragment(片段myNewFragment){
FragmentManager人= getSupportFragmentManager();
            如果(man.getBackStackEntryCount()大于0){
                INT N = man.getBackStackEntryCount();
                man.popBackStack(man.getBackStackEntryAt第(n-1).getName(),FragmentManager.POP_BACK_STACK_INCLUSIVE);
            }

        FragmentTransaction T = getSupportFragmentManager()的BeginTransaction()。
        t.replace(R.id.main_fragment,myNewFragment);
        t.commit();
    }
 

我希望能帮助你!

An SSCCE for this issue is available on GitHub.

For future readers, the original example is on a branch of the same project.

This SSCCE has a ListView and a row of buttons. The buttons are supposed to change the data in the ListView, and the listView rows (when clicked) are supposed to open a new fragment and advance the backstack while staying in the same activity.

If do the following things, it produces the following result:

  1. Open the app.
  2. Tap the ListView. - FragmentTransaction.replace(...) with addToBackStack(true)
  3. Tap any of the buttons. - FragmentTransaction.replace(...) with addToBackStack(false)
  4. Tap the back button.

Result:

Both fragments become visible, but I only want the first loaded fragment (ListTwoFragment in code) to display. Is this how fragments are supposed to work? If so, how can I get the desired effect?

MainActivity.java:

public class MainActivity extends FragmentActivity implements ListTwoFragment.Callbacks,
    ListThreeFragment.Callbacks {
    public static final String KEY_ARGS = "args";

    private String curUri = "";
    private String curArgs = "";

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

        selectContent(false);
    }

    private void selectContent(boolean addToBackStack) {
        Fragment fragment;

        if (curUri.isEmpty()) {
            // Use default fragment
            fragment = new ListTwoFragment();
            curUri = ListTwoFragment.class.getName();
        }
        else {
            try {
                Class<Fragment> fragmentClass = (Class<Fragment>) Class.forName(curUri);
                fragment = fragmentClass.newInstance();
            }
            catch (Exception e) { // ClassNotFound, IllegalAccess, etc.
                return;
            }
        }

        // Configure fragment
        Bundle args = new Bundle();
        args.putString(KEY_ARGS, curArgs);
        fragment.setArguments(args);

        attachFragment(fragment, addToBackStack, curUri + ";" + curArgs, R.id.fragment_container);
    }

    protected void attachFragment(Fragment fragment, boolean addToBackStack, String tag, int replaceId) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(replaceId, fragment, tag);
        if (addToBackStack) transaction.addToBackStack(tag);
        transaction.commit();
    }

    @Override
    public void onTwoButtonClick(String title) {
        curUri = ListTwoFragment.class.getName();
        curArgs = title;
        selectContent(false);
    }

    @Override
    public void onTwoListClick() {
        curUri = ListThreeFragment.class.getName();
        curArgs = "";
        selectContent(true);
    }

    @Override
    public void onThreeButtonClick(String title) {
        curUri = ListThreeFragment.class.getName();
        curArgs = title;
        selectContent(false);
    }
}

解决方案

I'm working with Fragments to, and the way I'm doing it: to go forward (add to stack), and backwords (remove from stack) are two different functions

to Add to Stack and change Fragment:

public void changeFragmentAddToStack(Fragment myNewFragment) {
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.add(R.id.main_fragment, myNewFragment);
        t.addToBackStack(null);
        t.commit();
    }

To go back Stack:

        public void goBackStackMain() {
    FragmentManager man = getSupportFragmentManager();

                if(man.getBackStackEntryCount()>0){ 
                    man.popBackStack(man.getBackStackEntryAt(0).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
            }
}

And if you want to do both: To go back stack and change fragment:

    public void goBackStackAndReplaceFragment(Fragment myNewFragment) {
FragmentManager man = getSupportFragmentManager();
            if(man.getBackStackEntryCount()>0){ 
                int n = man.getBackStackEntryCount();
                man.popBackStack(man.getBackStackEntryAt(n-1).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
            }

        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.main_fragment, myNewFragment);
        t.commit();
    }

I hope to help you !

这篇关于片段行为异常使用addToBackStack当()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆