定向改变后片段无法正常工作

时间:2012-06-18 14:56:36

标签: android android-fragments

我遇到了Fragments和方向更改的问题。

我有一个应用程序,其MainActivity通过选项卡式操作栏处理切换Fragments。以下是选项卡式操作栏的代码以及选择选项卡的时间。

private class MyTabListener <T extends android.support.v4.app.Fragment> implements ActionBar.TabListener {
    private android.support.v4.app.Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    public MyTabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    @Override
    public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) {
        if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one.
            mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content,mFragment,mTag);
        } else {
            ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity
        }
    }

    @Override
    public void onTabUnselected(Tab tab, android.support.v4.app.FragmentTransaction ft) {
        if (mFragment != null){
            ft.detach(mFragment); // when a fragment is no longer needed, detach it from the activity but dont destroy it
        }
    }

    @Override
    public void onTabReselected(Tab tab, android.support.v4.app.FragmentTransaction ft) {

    }

我看到的方式是,当应用程序首次以纵向模式加载时,一切正常。当我旋转时,由于某种原因,添加了Fragment1的另一个实例,然后在选择另一个选项卡时不会分离。当我然后旋转回肖像时也是这种情况。

我已尝试在setRetainInstance(true);中使用Fragments,但这不起作用。

在旋转之前,我是否需要覆盖或使用Fragments执行某些操作?

提前致谢。

编辑我现在已经看到在重新创建活动时再次调用onTabSelected。这可能是我的问题的原因,片段连接不止一次?

这是我关于创建方法的活动。

super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
           //setContentView(R.layout.main);

        }
     // Create the Action Bar with tabs
        ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowTitleEnabled(false);
        //create the tab for track and add it to the action bar.
        Tab tab = actionBar.newTab()
                            .setText("Track")
                            .setTabListener(new MyTabListener<TrackingFragment>(this,"track",TrackingFragment.class));
        actionBar.addTab(tab);

        //create the tab for ski tracks and add it to the action bar.
        tab = actionBar.newTab()
                        .setText("Something Tracks")
                        .setTabListener(new MyTabListener<TrackListFragment>(this,"somethingtracks",TrackListFragment.class));
        actionBar.addTab(tab);

        //create the tab for photos and add it to the action bar.
        tab = actionBar.newTab()
                        .setText("Photos")
                        .setTabListener(new MyTabListener<PhotoFragment>(this,"photos",PhotoFragment.class));
        actionBar.addTab(tab);

5 个答案:

答案 0 :(得分:16)

简短修复:

onTabSelected方法中,在使用if (mFragment == null)之前,您需要尝试获取片段(使用mFragment = getSupportFragmentManager().findFragmentByTag(mTag))。你也可以从外面设置这个,但我不认为你这样做。

检查if(savedInstanceState == null)上的onCreate也可以解决这个问题,我认为这是一个更好的方法! :)

答案 1 :(得分:8)

听起来你的onCreate方法中没有包含在if(savedInstanceState == null)中的东西,所以除了从savedInstanceState包中恢复的片段外,你还要创建另一个片段。

修改

仔细观察你的代码,我认为onCreate我错了,你的onTabSelected应该处理它。我认为你的if (mFragment == null)总是空出来,因为你没有尝试找到这个片段。将该代码部分更改为:

@Override 
public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 

    mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag);   // add this

    if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one. 
        mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
        ft.add(android.R.id.content,mFragment,mTag); 
    } else { 
        ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity 
    } 
} 

答案 2 :(得分:2)

我发现setRetainInstance实际上已被忽略,android.support.v4.app.FragmentManager创建的所有片段都存储在onSaveInstanceState中,并在onCreate中重新创建。

对我来说,解决方案是直截了当地删除多余的片段:https://stackoverflow.com/a/13996054/341091

答案 3 :(得分:1)

我或多或少有同样的问题,但上面提到的解决方案在我的情况下似乎没有成功。最终我找到了以下解决方案:

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    if (mFragment == null) {
        mFragment = Fragment.instantiate(mActivity, mClass.getName());
        ft.replace(android.R.id.content, mFragment, mTag); // Use replace iso add
    }
    else {
        ft.attach(mFragment);
    }
}

答案 4 :(得分:0)

if(savedInstanceState == null)始终不起作用。有时savedInstanceState!= null,因为横向方向需要添加另一个片段。

另一种方法是测试fm.findFragmentById(R.id.frameLayoutLeft),无论方向是什么,是否为null,如果是,则创建新的片段实例,否则什么也不做。如果在横向模式下需要第二个片段,则首先需要检查它是否为横向,如果是,请检查fm.findFragmentById(R.id.frameLayoutRight)是否为空。如果为null,则为create,否则不执行任何操作,因为它已经由Android OS保留。