ViewPager onPageSelected 第一页

23

看起来在使用ViewPager时,onPageSelected监听器不会对第一页调用,与此问题相同。

我有一些逻辑来填充当前选定页面的一些更昂贵的UI元素,在页面更改时这些逻辑可以正常工作,但是在第一页时它不起作用。

如果我在监听器之后设置当前项,回调将为第一页触发,但是视图尚未初始化,因此我无法操作它:

// Inside PagerAdapter.instantiateItem

ViewHolder vh = new ViewHolder();
cursor.moveToPosition(position);
vh.view = adapter.newView(context, cursor, null);
// Set position as tag so we can retrieve it with findViewByTag
vh.view.setTag(position); 

((ViewPager) collection).addView(vh.view,0);       

return vh;

// Inside MyActivity.onCreate

pagerAdapter = new SingleMessagePagerAdapter(this, cursor);
pager = (ViewPager)findViewById(R.id.message_pager);
pager.setAdapter(pagerAdapter);
pager.setOnPageSelectedListener(this);
pager.setCurrentItem(selectedItem);

// Inside MyActivity.onPageSelected

// Retrieve tagged view
View view = pager.findViewWithTag(position); 

这里view最终变成了null,因为PagerAdapter.instantiateItem尚未运行。所以我的问题是,在活动生命周期的哪个阶段我可以确定ViewPager已经初始化了视图?我尝试在Activity.onAttachedToWindowActivity.onResume内部执行此操作,但似乎两者都在PagerAdapter.instantiateItem之前触发。

3个回答

5
我想知道为什么你不把提到的逻辑放在Fragment本身而不是托管Activity中。ViewPager缓存当前页面两侧的几个片段,因此它们在后台设置好并准备好在用户切换到它们时使用。将逻辑放在onPageSelected中意味着绕过此功能,并且直到用户切换到该页面才执行重型操作。
假设由于某种原因你无法执行上述操作,为什么不使用带有回调函数的接口。在片段的onCreateView函数中触发回调以让Activity知道它已完全实例化。

2

尝试使用片段!

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter() {
        super(getSupportFragmentManager());
    }

    @Override
    public Fragment getItem(int i) {
        Fragment fr = null;
        if (i==0)
           fr = new sec0frag();
        else if (i==1)
           fr = new sec1frag();
        else if (i==2)
           fr = new sec2frag();
        return fr;
    }

    @Override
    public int getCount() {
        return 3;
    }
}

并创建3个片段类

例如:

    public static class sec0frag extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
                     // here is initialize for first time to view pages.!
        }
    }

这应该可以工作,但如果您必须滚动浏览一个未预定义页面数量的页面列表怎么办?比如从网络中获取一系列项目,并且每个项目都需要逐个在这些页面中显示? - Aman Alam
在FragmentPagerAdapter中动态定义getCount(),或者尝试在ViewPager中启用循环! - SeSajad

1
我的解决方案是扩展pager adapter并在其中创建一个接口。然后让adapter在创建后仅调用一次该接口。在接口回调中,您可以调用onPageChanged方法而不会出现nullpointerexception。将此类添加到您的项目中,并从中扩展您的adapter。在将adapter设置到viewpager之前,请不要忘记将监听器设置为adapter。适配器类如下:
public abstract class ExtendedPagerAdapter extends FragmentPagerAdapter {

private boolean instantiated;
private AdapterListener adapterListener;

public interface AdapterListener {
    void onAdapterInstantiated();
}

public ExtendedPagerAdapter(FragmentManager fragmentManager) {
    this(fragmentManager, null);
}

public ExtendedPagerAdapter(FragmentManager fragmentManager, AdapterListener adapterListener) {
    super(fragmentManager);
    this.adapterListener = adapterListener;
    instantiated = false;
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
    if (!instantiated) {
        instantiated = true;
        if (adapterListener != null) {
            adapterListener.onAdapterInstantiated();
        }
    }
}

public void setAdapterInstantiatedListener(AdapterListener adapterListener) {
    this.adapterListener = adapterListener;
}
}

活动代码:

adapter = new ViewPagerAdapter(getChildFragmentManager());
    adapter.setAdapterInstantiatedListener(new ExtendedPagerAdapter.AdapterListener() {
        @Override
        public void onAdapterInstantiated() {
            onPageSelected(viewPager.getCurrentItem());
        }
    });

    viewPager.addOnPageChangeListener(this);
    viewPager.setAdapter(adapter);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接