始终为索引0和1调用Viewpager Adapter getItem

时间:2015-09-02 09:00:16

标签: android android-viewpager position adapter

我只是想知道viewpager及其适配器的正常行为是否总是为索引0和1调用getItem()方法,即使我立即设置了当前位置。

这是我的代码:

mNewsPagerAdapter = new NewsDetailPagerAdapter(getChildFragmentManager());
mNewsPagerAdapter.updateNewsList(news);

mViewPager = (ViewPager) mView.findViewById(R.id.horizontal_view_pager);
mViewPager.setPageMargin(2);
mViewPager.setPageMarginDrawable(R.color.black);

mViewPager.setAdapter(mNewsPagerAdapter);
mViewPager.setCurrentItem(mCurrentPositionPager, false);

如果我使用此viewpager从概述活动切换到我的详细活动,则适配器始终调用位置0和1的getItem()方法,然后调用getItem()方法mOriginalPosition及其邻居的位置。我想知道这是否是正确的行为,或者我错过了以正确的方式实现它的东西。谢谢你的帮助:)

编辑:添加了我的适配器代码

public class NewsDetailPagerAdapter extends FragmentStatePagerAdapter {

private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>();

private ArrayList<News> mNewsList;

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

/**
 * Setzt die neuen News.
 **/
public void updateNewsList(ArrayList<News> list) {
    mNewsList = list;
}

@Override
public Fragment getItem(int position) {
    Log.d("debug", "getItem position:" + position);
    News newsItem = mNewsList.get(position);


    NavigationFragment fragment = new NavigationFragment();

    mPageReferenceMap.put(position, fragment);

    return fragment;
}


@Override
public int getCount() {
    return mNewsList.size();
}

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

public Fragment getFragment(int position) {
    return mPageReferenceMap.get(position);
}

}

4 个答案:

答案 0 :(得分:2)

是的,这是ViewPager的正常行为,因为它总是会尝试通过渲染限制绘图区域的选项卡来保持领先于用户。我个人不建议创建自定义ViewPager,因为除非你真的知道自己在做什么,否则几乎肯定会破坏功能。您的适配器类应如下所示:

public class YourCustomPagerAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> fragmentList = new ArrayList<>();
    private List<String> titleList = new ArrayList<>();

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

    public void addFragment(Fragment fragment, String title) {
        fragmentList.add(fragment);
        titleList.add(title);
    }

    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        super.getPageTitle(position);
        return titleList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList.size();
    }
}

你应该添加你的片段:

 @Override
 public void onCreate(Bundle savedInstanceState) {
     ...
     YourCustomPagerAdapter adapter = new YourCustomPagerAdapter (getSupportFragmentManager());
     adapter.addFragment(FragmentOne.newInstance(), "Frag 1");
     adapter.addFragment(FragmentTwo.newInstance(), "Frag 2");
     viewPager.setAdapter(adapter);
     ...
 }

答案 1 :(得分:2)

这是正常的(在我看来是聪明的)。 ViewPager类有一个名为mOffscreenPageLimit的属性,默认值为1.此数字确定Viewpager将预加载的当前页面左侧和右侧的页数。例如,您有10页,当前位置为5,mOffcreenPageLimit为1,将加载位置4和6的页面。

您可以通过调用此方法来更改此属性

viewpager. setOffscreenPageLimit(int)

如果传入的小于1的整数,则无效。

答案 2 :(得分:1)

实际上这是男性行为。事实上,作为将ViewPager与适配器相关联的soos,适配器创建第一个visibile布局(索引0)结束下一个(索引1)。默认情况下,这在“setAdapter”中完成。然后,当您设置不同的位置时,适配器将在所选索引(前一个和下一个索引)处实例化该片段。

这是通常的ViewPager setAdapter代码:

public void setAdapter(PagerAdapter adapter) {
    if (mAdapter != null) {
        mAdapter.setViewPagerObserver(null);
        mAdapter.startUpdate(this);
        for (int i = 0; i < mItems.size(); i++) {
            final ItemInfo ii = mItems.get(i);
            mAdapter.destroyItem(this, ii.position, ii.object);
        }
        mAdapter.finishUpdate(this);
        mItems.clear();
        removeNonDecorViews();
        mCurItem = 0;
        scrollTo(0, 0);
    }

    final PagerAdapter oldAdapter = mAdapter;
    mAdapter = adapter;
    mExpectedAdapterCount = 0;

    if (mAdapter != null) {
        if (mObserver == null) {
            mObserver = new PagerObserver();
        }
        mAdapter.setViewPagerObserver(mObserver);
        mPopulatePending = false;
        final boolean wasFirstLayout = mFirstLayout;
        mFirstLayout = true;
        mExpectedAdapterCount = mAdapter.getCount();
        if (mRestoredCurItem >= 0) {
            mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader);
            setCurrentItemInternal(mRestoredCurItem, false, true);
            mRestoredCurItem = -1;
            mRestoredAdapterState = null;
            mRestoredClassLoader = null;
        } else if (!wasFirstLayout) {
            populate();
        } else {
            requestLayout();
        }
    }

    if (mAdapterChangeListener != null && oldAdapter != adapter) {
        mAdapterChangeListener.onAdapterChanged(oldAdapter, adapter);
    }
}

为了更改ViewPager行为,您可以扩展经典ViewPager覆盖setAdapter方法并将mCurrItem设置为所需位置。

我希望它有所帮助

编辑:

经过不同的测试,我们找到了解决方案。

如果在ViewPager布局可见后设置了ViewPager适配器,则会加载项目0和1。 如果要避免此行为,但在布局变为可见之前无法设置适配器(因为您正在等待数据),则可以使用此解决方法:

1)最初将ViewPager可见性设置为GONE

2)收到所有数据后,更新适配器并设置当前项值

3)最后,将ViewPager可见性设置为VISIBLE

在这里你可以找到一个例子:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View v = inflater.inflate(R.layout.detail_overview_fragment, container, false);

    final int position = getArguments().getInt("position");
    final ViewPager viewPager = (ViewPager) v.findViewById(R.id.viewpager);
    viewPager.setVisibility(View.GONE);

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            viewPager.setAdapter(new PagerAdapter(getChildFragmentManager()));
            viewPager.setCurrentItem(position);
            viewPager.setVisibility(View.VISIBLE);

        }
    },5000);

    return v;
}

答案 3 :(得分:-1)

我认为错误是适配器:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:top="@dimen/floating_hint_margin" android:bottom="@dimen/floating_hint_margin">
    <your original background; can be <bitmap> or <shape> or whatever./>
  </item>
</layer-list>

错误原因:此列表是该适配器的不同实体。