【问题标题】:FragmentPagerAdapter getItem() is returning more than it shouldFragmentPagerAdapter getItem() 返回的超出了应有的范围
【发布时间】:2015-08-03 15:17:47
【问题描述】:

我有一个MainActivity,它控制四个片段,每个片段都是一个选项卡。当我的主要活动开始时,我会在日志中打印一行以显示正在实例化的片段。这是我的 FragmentPagerAdapter:

public class TabsPagerAdapter extends FragmentPagerAdapter {

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

@Override
public Fragment getItem(int index) {

    switch (index) {
        case 0:
            System.out.println("Returning new PrearrivalPlan()");
            return new PrearrivalPlan();
        case 1:
            System.out.println("Returning new PrimarySurvey()");
            return new PrimarySurvey();
        case 2:
            System.out.println("Returning new SecondarySurvey()");
            return new SecondarySurvey();
        case 3:
            System.out.println("Returning new PrepareForTravel()");
            return new PrepareForTravel();
    }

    return null;
}

@Override
public int getCount() {
    // get item count - equal to number of tabs
    return 4;
}

}

标签栏按顺序有以下选项:

Prearrival Plan | Primary Survey | Secondary Survey | Prepare for Travel

当我的主要活动开始时,屏幕上会打印以下内容:

Returning new PrearrivalPlan() Returning new PrimarySurvey()

它似乎在做的是在我选择的标签之前加载一个标签。由于 PrearrivalPlan 是第一个选项卡,我认为它应该只返回一个新的PrearrivalPlan(),除非它同时返回两者。另一个例子,当我点击 Primary Survey 选项卡(第二个选项卡)时,屏幕上会打印以下内容:

Returning new SecondarySurvey() // <- This is the third tab!?

因为 PrimarySurvey 在 Activity 首次启动时已经实例化(参见上面的输出),所以它像以前一样向前跳转并加载了第三个选项卡,尽管我只单击了第二个选项卡。

这是我的MainActivity

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {

private CustomViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;

private String[] tabTitles = {"Pre-arrival Plan", "Primary Survey", "Secondary Survey", "Prepare for Travel"};

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    viewPager = (CustomViewPager) findViewById(R.id.pager);
    actionBar = getActionBar();
    mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

    viewPager.setAdapter(mAdapter);
    viewPager.setPagingEnabled(false);

    actionBar.setHomeButtonEnabled(true);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


    viewPager.setOnPageChangeListener(new CustomViewPager.OnPageChangeListener() {


        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            actionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }

    });

    // Remove Android icon from Action Bar
    getActionBar().setIcon(new ColorDrawable(getResources().getColor(android.R.color.transparent)));
    getActionBar().setDisplayShowHomeEnabled(false);

    // Add tabs to Action Bar
    for (String tab_name : tabTitles) {
        actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
    }

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

public void updateTabTitles(int tabNumber, int checkBoxesRemaining) {
    String text = tabTitles[tabNumber] + " \n             (" + checkBoxesRemaining + ")";
    actionBar.getTabAt(tabNumber).setText(text);
}

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
    viewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {

}

@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {

}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent intent = new Intent(this, MainMenu.class);
            startActivity(intent);
            return true;
        case R.id.complete:
            DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    switch (which){
                        case DialogInterface.BUTTON_POSITIVE:
                            goToReport();
                            break;
                        case DialogInterface.BUTTON_NEGATIVE:
                            //No button clicked
                            break;
                    }
                }
            };
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Are you sure you want to complete the checklist?").setPositiveButton("Yes", dialogClickListener).setNegativeButton("No", dialogClickListener).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

public void goToReport() {
    Intent intent = new Intent(this, Report.class);
    startActivity(intent);
}

【问题讨论】:

  • FragmentPagerAdapter getItem() 返回的比它应该返回的多 不,它不是.. 由 PagerAdapter 来调用 getItem ...那么你不应该使用它(也许你应该找到一些向导控件)
  • @Selvin 在标签页甚至一般的 android 开发方面我都是初学者,所以也许我只是误解了一些东西。

标签: android android-fragments tabs android-tabs


【解决方案1】:

这是 ViewPager 的预期行为。 ViewPager 总是在内存中前后保留一个标签以显示滑块动画。如果内存中没有下一个或上一个选项卡(或片段),则在滑块转换期间尝试启动片段将导致性能滞后,或者更糟糕的是,您将滑动片段为空并稍后加载.

ViewPager 还允许您通过setOffscreenPageLimit() 设置页面偏移限制,这将控制数量片段以将它们保留在内存中。默认情况下,这是 1,这意味着前后一个片段将始终存在于内存中

【讨论】:

  • 非常有用且内容丰富的评论,setOffscreenPageLimit() 解决了我在标签的行为与我在上面发布的内容之外的预期不同时遇到的问题。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 2014-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
相关资源
最近更新 更多