首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >带ActionBar的双片段旋转安卓系统

带ActionBar的双片段旋转安卓系统
EN

Stack Overflow用户
提问于 2012-02-26 17:21:47
回答 4查看 7K关注 0票数 18

我做了一个简单的安卓活动,用一个ActionBar在两个片段之间切换。在我转动设备之前一切都没问题。事实上,当我旋转时,我得到了两个片段,一个在另一个上面:前一个活动的和第一个的。为什么?如果轮转破坏并重新创建了我的活动,为什么我会获得2个碎片?

示例代码:

活动

代码语言:javascript
复制
package rb.rfrag.namespace;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.os.Bundle;

    public class RFragActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Notice that setContentView() is not used, because we use the root
        // android.R.id.content as the container for each fragment

     // setup action bar for tabs
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        //actionBar.setDisplayShowTitleEnabled(false);

        Tab tab;
        tab = actionBar.newTab()
                .setText(R.string.VarsTab)
                .setTabListener(new TabListener<VarValues>(
                        this, "VarValues", VarValues.class));
        actionBar.addTab(tab);

        tab = actionBar.newTab()
                .setText(R.string.SecTab)
                .setTabListener(new TabListener<SecFrag>(
                        this, "SecFrag", SecFrag.class));
        actionBar.addTab(tab);
    }
}

TabListener

代码语言:javascript
复制
package rb.rfrag.namespace;

import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ActionBar.Tab;

public class TabListener<T extends Fragment> implements ActionBar.TabListener {
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /** Constructor used each time a new tab is created.
      * @param activity  The host Activity, used to instantiate the fragment
      * @param tag  The identifier tag for the fragment
      * @param clz  The fragment's Class, used to instantiate the fragment
      */
    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {    
        // Check if the fragment is already initialized
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-27 05:41:48

我已经解决了在活动中使用onSaveInstanceStateonRestoreInstanceState来维护所选选项卡并修改onTabSelected的问题,如下所示。

最后一个修改器避免了Android重新构建它没有拆卸的碎片。然而,我不明白为什么活动会被旋转事件破坏,而当前的片段没有。(你对此有什么想法吗?)

代码语言:javascript
复制
public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // previous Fragment management
        Fragment prevFragment;
        FragmentManager fm = mActivity.getFragmentManager();
        prevFragment = fm.findFragmentByTag(mTag); 
        if (prevFragment != null) { 
            mFragment = prevFragment; 
        } // \previous Fragment management

        // Check if the fragment is already initialized
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }
    }
票数 21
EN

Stack Overflow用户

发布于 2012-12-22 03:29:43

因为我使用的是覆盖onTabSelectedandroid.support.v4.view.ViewPager,所以不会有什么帮助。但你的暗示还是给我指明了正确的方向。

android.support.v4.app.FragmentManager将所有片段保存在android.support.v4.app.FragmentActivityonSaveInstanceState中。忽略 setRetainInstance -根据您的设计,这可能会导致重复的片段。

最简单的解决方案是删除活动的orCreate中保存的片段:

代码语言:javascript
复制
   @Override
   public void onCreate (final android.os.Bundle savedInstanceState)
   {
      if (savedInstanceState != null)
      {
         savedInstanceState.remove ("android:support:fragments");
      } // if

      super.onCreate (savedInstanceState);
…
      return;
   } // onCreate
票数 11
EN

Stack Overflow用户

发布于 2013-03-08 15:33:43

该解决方案实际上并不需要大量的工作,以下步骤可确保在旋转屏幕时保持选项卡选择。我遇到了重叠的片段,因为在屏幕旋转时,我的第一个标签被选中,而不是在旋转屏幕之前选择的第二个标签,因此第一个标签与第二个标签的内容重叠。

这是你的活动应该看起来的样子(我使用的是ActionBarSherlock,但是调整它应该很容易):

代码语言:javascript
复制
public class TabHostActivity extends SherlockFragmentActivity {

   private static final String SELETED_TAB_INDEX = "tabIndex";


   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

     // Setup the action bar
     ActionBar actionBar = getSupportActionBar();
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

     // Create the Tabs you need and add them to the actionBar...

     if (savedInstanceState != null) {
        // Select the tab that was selected before orientation change
        int index = savedInstanceState.getInt(SELETED_TAB_INDEX);
        actionBar.setSelectedNavigationItem(index);
     }
   }

   @Override
   protected void onSaveInstanceState(Bundle outState) {
     super.onSaveInstanceState(outState);
     // Save the index of the currently selected tab 
     outState.putInt(SELETED_TAB_INDEX, getSupportActionBar().getSelectedTab().getPosition());
   }
}

这是我的ActionBar.TabListener的样子(它是上面活动中的一个私有类):

代码语言:javascript
复制
  private class MyTabsListener<T extends Fragment> implements ActionBar.TabListener {
     private Fragment fragment;
     private final SherlockFragmentActivity host;
     private final Class<Fragment> type;
     private String tag;

     public MyTabsListener(SherlockFragmentActivity parent, String tag, Class type) {
        this.host = parent;
        this.tag = tag;
        this.type = type;
     }

     @Override
     public void onTabSelected(Tab tab, FragmentTransaction transaction) {
        /*
         * The fragment which has been added to this listener may have been
         * replaced (can be the case for lists when drilling down), but if the
         * tag has been retained, we should find the actual fragment that was
         * showing in this tab before the user switched to another.
         */
        Fragment currentlyShowing = host.getSupportFragmentManager().findFragmentByTag(tag);

        // Check if the fragment is already initialised
        if (currentlyShowing == null) {
          // If not, instantiate and add it to the activity
          fragment = SherlockFragment.instantiate(host, type.getName());
          transaction.add(android.R.id.content, fragment, tag);
        } else {
          // If it exists, simply attach it in order to show it
          transaction.attach(currentlyShowing);
        }
     }

     public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
        /*
         * The fragment which has been added to this listener may have been
         * replaced (can be the case for lists when drilling down), but if the
         * tag has been retained, we should find the actual fragment that's
         * currently active.
         */
        Fragment currentlyShowing = host.getSupportFragmentManager().findFragmentByTag(tag);
        if (currentlyShowing != null) {
          // Detach the fragment, another tab has been selected
          fragmentTransaction.detach(currentlyShowing);
        } else if (this.fragment != null) {
          fragmentTransaction.detach(fragment);
        }
     }

     public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
        // This tab is already selected
     }

上面的实现还允许基于标签替换选项卡内的片段。为此,当在同一选项卡中切换片段时,我使用与添加到选项卡中的初始框架相同的标记名。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9451917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档