Android Action Bar 选项卡 - 内部 fragment 事务问题

标签 android android-fragments actionbarsherlock android-actionbar

我已经使用来自 Google 自己的以下示例成功地在操作栏中设置了选项卡 http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html作为基地。我的代码如下所示:

public class Main extends SherlockFragmentActivity {

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);        

    getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    ActionBar.Tab tab1 = getSupportActionBar().newTab();
    tab1.setIcon(R.drawable.ic_tab_example_selected);
    tab1.setTabListener(new TabListener<Tab1>(this, "A", Tab1.class));
    getSupportActionBar().addTab(tab1);

    ActionBar.Tab tab2 = getSupportActionBar().newTab();
    tab2.setIcon(R.drawable.ic_tab_example_selected);
    tab2.setTabListener(new TabListener<Tab2>(this, "B", Tab2.class));
    getSupportActionBar().addTab(tab2);

    ActionBar.Tab tab3 = getSupportActionBar().newTab();
    tab3.setIcon(R.drawable.ic_tab_example_selected);
    tab3.setTabListener(new TabListener<Tab3>(this, "C", Tab3.class));
    getSupportActionBar().addTab(tab3);

    ActionBar.Tab tab4 = getSupportActionBar().newTab();
    tab4.setIcon(R.drawable.ic_tab_example_selected);
    tab4.setTabListener(new TabListener<Tab4>(this, "D", Tab4.class));
    getSupportActionBar().addTab(tab4);     
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return true;
}

public class TabListener<T extends Fragment> implements ActionBar.TabListener {
    private Fragment mFragment;
    private final SherlockFragmentActivity 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(SherlockFragmentActivity 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);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}
}

有了这个,我有多个选项卡,可以在每个选项卡中的不同 fragment 之间切换。但是,我的问题是在选项卡中并从选项卡中更改 fragment 时开始的。这是问题所在:

当我在 Tab 1 中时,我用一个新 fragment 交换选项卡中加载的初始 fragment 。然后我转到 Tab 2,它显示了它的初始 fragment 。但是,在 Tab 1 中交换到的 fragment 的 View 仍然显示在 Tab 2 fragment 后面:

Tab 1, Fragment 2 Tab2, Fragment 1

这是我目前用于更改 Tab 1 中的 fragment 的代码:

// Create new fragment and transaction
    FragmentTransaction transaction = ctx.getFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

    // Replace whatever is in the fragment_container view with this fragment,
    // and add the transaction to the back stack
    transaction.replace(container, fragment, tag);

    if(addToBackStack)
        transaction.addToBackStack(tag);

    // Commit the transaction
    transaction.commit();

所有这些都是通过 ActionBar Sherlock 和 Google v4 支持库完成的。

最佳答案

好的,所以这个答案假设您希望在每次交换标签时删除每个标签的历史记录。我的意思是 Tab 1 从 frag 1 开始,然后单击并将其更改为 frag 2。如果选择 Tab 2,将撤消 Tab 1 的历史记录,下次单击 Tab 1 时将返回到 fragment 1.

这里说的是解决方案:用下面的替换你的 onTabUnselected

public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            //this segment removes the back history of everything in the tab you are leaving so when you click on the tab again you go back to a fresh start
            FragmentManager man = mActivity.getFragmentManager();
            if(man.getBackStackEntryCount()>0) //this check is required to prevent null point exceptions when clicking off of a tab with no history
                man.popBackStack(man.getBackStackEntryAt(0).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); //this pops the stack back to index 0 so you can then detach and then later attach your initial fragment
            //also it should be noted that if you do popbackstackimmediate here instead of just popbackstack you will see a flash as the gui changes back to the first fragment when the code executes
            //end
            ft.detach(mFragment);
        }
    }

关于Android Action Bar 选项卡 - 内部 fragment 事务问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9941172/

相关文章:

Android 应用安装尝试失败,出现 : Failure [INSTALL_FAILED_OLDER_SDK]

java - 谷歌地图返回空指针异常

android - 如何实现saveFragmentInstanceState?

android - 使用选项卡在 ActionBar 中调用 onCreateOptionsMenu 的次数太多

android - ViewPager + Fragments - 未显示 fragment

android - 如何使用 ActionBarSherlock 更改 Actions 的触摸影响颜色?

java - 获取外部存储目录不起作用

android - AudioFlinger 无法创建效果,状态 : -22

android - Android 12 中的 IntentFilter 和导出组件是否有任何(记录不详的)更改?

android - 没有简单的方法在新屏幕中显示 PreferenceFragment?