简体   繁体   English

Android - 带有动态标签数量的 tabbedActivity

[英]Android - tabbedActivity with dynamic number of tabs

I'm creating an app which (according to chosen mode) has to have 2 or 3 tabs in a tabbed activity.我正在创建一个应用程序(根据选择的模式)在选项卡式活动中必须有 2 或 3 个选项卡。 When I choose the mode with three tabs, everything's fine, but mode requiring 2 tabs throws this exception:当我选择带有三个选项卡的模式时,一切都很好,但是需要 2 个选项卡的模式会引发此异常:

java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! java.lang.IllegalStateException:应用程序的 PagerAdapter 更改了适配器的内容,而没有调用 PagerAdapter#notifyDataSetChanged! Expected adapter item count: 3, found: 2 Pager id: abm.ant8.sotgtests:id/container Pager class: class android.support.v4.view.ViewPager Problematic adapter: class abm.ant8.sotgtests.MainActivity$SectionsPagerAdapter预期的适配器项目数:3,找到:2 寻呼机 ID:abm.ant8.sotgtests:id/container 寻呼机类:类 android.support.v4.view.ViewPager 有问题的适配器:类 abm.ant8.sotgtests.MainActivity$SectionsPagerAdapter

When I comment out this.notifyDataSetChanged() (marked HERE), it crashes on both cases.当我注释掉 this.notifyDataSetChanged()(在此处标记)时,它在两种情况下都会崩溃。 Here's my PagerAdapter code (I'm using v4 support package):这是我的 PagerAdapter 代码(我使用的是 v4 支持包):

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            mExplanationFragment = ExplanationFragment.newInstance();
            mQuestionFragment = QuestionFragment.newInstance(totalNoOfQuestions);
            if (mode == LEARNING_MODE) {
                mRulesFragment = RulesFragment.newInstance();
            }
            Fragment fragment;

            if (mode == TESTING_MODE) {
                if (position == 1) {
                    fragment = mExplanationFragment;
                } else {
                    fragment = mQuestionFragment;
                }
            } else {
                if (position == 2) {
                    fragment = mExplanationFragment;
                } else if (position == 1){
                    fragment = mQuestionFragment;
                } else  {
                    fragment = mRulesFragment;
                }
            }

            //this.notifyDataSetChanged(); HERE
            return fragment;
        }

        @Override
        public int getCount() {
            if (mode == TESTING_MODE) {
                return 2;
            } else {
                return 3;
            }
        }
        //...
        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }
}

This is already after applying hints from this SO topic , others looked very similar.这已经是在应用了这个 SO 主题的提示之后,其他人看起来非常相似。 Is this approach (taken directly from Android Studio wizard) correct at all for this situation?对于这种情况,这种方法(直接取自 Android Studio 向导)是否完全正确? Looks like defining default start tab as middle, instead of the first one, is going to be a hassle as well (but that's of course for another question, after I solve this problem).看起来将默认开始选项卡定义为中间,而不是第一个,也会很麻烦(但这当然是另一个问题,在我解决这个问题之后)。

EDIT: as a brute-force solution, I'm thinking of simply copying the current Activity and slightly modifying it, so that it won't be an Activity called with extras in intent, rather calling different Activities.编辑:作为一个蛮力的解决方案,我正在考虑简单地复制当前的活动并稍微修改它,这样它就不会是一个意图额外调用的活动,而是调用不同的活动。 Since most of the needed functionality is already implemented (and much of it in fragments), this is definitely the fastest way to go.由于大部分需要的功能已经实现(并且大部分在片段中),这绝对是最快的方式。 To keep it modular and clean I can just do some refactoring and move methods common for both Activities into separate class.为了保持模块化和整洁,我可以进行一些重构并将两个活动通用的方法移动到单独的类中。

I ended up creating two separate Adapters, invoking them in hosting Activity:我最终创建了两个单独的适配器,在托管活动中调用它们:

if (mode == LEARNING_MODE) {
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setCurrentItem(1);
} else {
    mTwoSectionsPagerAdapter = new TwoSectionsPagerAdapter(getSupportFragmentManager());
    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mTwoSectionsPagerAdapter);
}

So these PagerAdapters just differed in getCount() and of course in providing proper Fragments in respective places ( getItem() method).所以这些 PagerAdapter 只是在getCount()和当然在各自的地方提供适当的片段( getItem()方法)上有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM