【问题标题】:Fragments Not Working Correctly After Orientation Change方向更改后片段无法正常工作
【发布时间】:2012-06-18 14:56:36
【问题描述】:

我遇到了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 实例,然后在选择另一个选项卡时不会分离。当我旋转回纵向时也是这种情况。

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

在旋转之前我需要覆盖或对我的Fragments 执行某些操作吗?

提前致谢。

EDIT 我现在看到在重新创建活动时再次调用了 onTabSelected。这可能是我多次附加片段问题的原因吗?

这是我的活动 onCreate 方法。

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);

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    短期修复:

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

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

    【讨论】:

    • 如果我将操作条码放在 onCreate 方法中,则在方向更改后重新创建活动时,它不会被创建或显示。我现在就试试 supportManager 部分
    • +1... 在我编辑的时候偷偷带上正确的答案。 :)
    • 调用setTabListener时是不是fragment没有传入?
    • 好吧,看看构造函数。 ` public MyTabListener(SherlockFragmentActivity activity, String tag, Class clz)`... 一个活动、一个标签和一个类。没有片段传入那里。
    • 没问题,佩德罗先想出来的。如果我的贡献对您有帮助,您可以投票支持我的答案,而无需将其选为已接受的答案。
    【解决方案2】:

    听起来您的 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 
        } 
    } 
    

    【讨论】:

    • 我们是在我的片段还是我的主要活动中谈论?
    • 我会冒险猜测您的主要活动。无论您设置什么并显示您的初始视图。
    • 我在上面的问题中添加了我的 onCreate 方法
    • 更新了我的答案。我想我走错了方向。
    【解决方案3】:

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

    对我来说,解决方案是直接删除多余保存的片段:https://stackoverflow.com/a/13996054/341091

    【讨论】:

      【解决方案4】:

      我或多或少遇到了同样的问题,但上面介绍的解决方案似乎不适用于我的情况。最终我找到了以下解决方案:

      @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);
          }
      }
      

      【讨论】:

        【解决方案5】:

        if(savedInstanceState == null) 并不总是有效。有时 savedInstanceState != null 因为横向需要添加另一个片段。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-22
          • 1970-01-01
          • 1970-01-01
          • 2015-10-13
          • 1970-01-01
          • 1970-01-01
          • 2020-06-10
          相关资源
          最近更新 更多