viewpager2 无限滚动

Infinite scrolling in viewpager2

如何在ViewPager2中实现无限滚动

因为这个寻呼机里没有OnPageChangeListener()。 但是有 setPageTransformer() 侦听器,每当我们更改页面时都会得到回调。

那么 viewpager2 问题的任何解决方案

注意:我正在为 viewpager2 使用 recyclerview 适配器

您可以使用下面的代码

public class YourPagerAdapter extends FragmentStatePagerAdapter
{
    public static int COUNT_OF_LOOP = 1000;
    private ArrayList<Product> mProducts;


    public YourPagerAdapter(FragmentManager manager, ArrayList<Product> products)
    {
        super(manager);
        mProducts = products;
    }


    @Override
    public Fragment getItem(int position)
    {
        if (mProducts != null && mProducts.size() > 0)
        {
            position = position % mProducts.size(); 
            return MyFragment.newInstance(mProducts.get(position));
        }
        else
        {
            return MyFragment.newInstance(null);
        }
    }


    @Override
    public int getCount()
    {
        if (mProducts != null && mProducts.size() > 0)
        {
            return mProducts.size()*COUNT_OF_LOOP;
        }
        else
        {
            return 1;
        }
    }
} 

mAdapter = new YourPagerAdapter(getSupportFragmentManager(), mProducts);
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mViewPager.getChildCount() * YourPagerAdapter. COUNT_OF_LOOP / 2, false);

步骤 1:创建 EndlessScrollAdapter class

class EndlessScrollAdapter internal constructor(
    fm: FragmentManager,
    lifeCycle: Lifecycle
) : FragmentStateAdapter(fm, lifeCycle) {

    private val items = mutableListOf<Model>()
    val firstElementPosition = Int.MAX_VALUE / 2

    fun updateList(list: List<Model>) {
        items.apply {
            clear()
            addAll(list)
        }
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int = if (items.isNotEmpty()) Int.MAX_VALUE else 0

    override fun createFragment(position: Int): Fragment = ViewPagerFragment(
        items[position.rem(items.size)])
}

步骤:2 从 Activity 或 Fragment

调用
viewPager2.adapter = endlessScrollAdapter
endlessScrollAdapter.apply {
  updateList(someModelList)
  viewPager2.setCurrentItem(this.firstElementPosition, false)
}

从字面上看,它不是无止境的,但从用户的角度来看,它是无止境的,因为他永远不会到达边缘。 ViewPager2 的长度为 Int.MAX_VALUE,起始位置为 Int.MAX_VALUE/2,因此用户可以向前和向后滚动。

试试下面的代码

@Override
public void onPageScrollStateChanged (int state) {
    if (state == ViewPager.SCROLL_STATE_IDLE) {
        int curr = viewPager.getCurrentItem();
        int lastReal = viewPager.getAdapter().getCount() - 2;
        if (curr == 0) {
            viewPager.setCurrentItem(lastReal, false);
        } else if (curr > lastReal) {
            viewPager.setCurrentItem(1, false);
        }
    }
}

希望对您有所帮助!

谢谢。

对于无限滚动,您不必自定义视图分页器。 viewPager 适配器中的技巧。您可以在 getCount 覆盖方法中 return Int.MAX 值。在 instantiateItem 覆盖函数中,您可以使用 item_position % item_size 来获取实际项目位置。代码示例如下。

class AdsSliderAdapter(
private val bannerImageList: MutableList<SliderImagesItem>,
private val callback: SliderItemClickListener) :PagerAdapter() {

private var mContext: Context? = null
override fun instantiateItem(container: ViewGroup, position: Int): Any {
    mContext = container.context

    val view = LayoutInflater.from(container.context)
        .inflate(R.layout.item_ad_slider, container, false)

    val adImage: AppCompatImageView = view.ivAd
    mContext?.let {
        GlideApp.with(it).load(bannerImageList[position % bannerImageList.size].imageUrl)
            .into(adImage)
    }
    val viewPager = container as ViewPager
    viewPager.addView(view, 0)

    view.cardView.onClick { callback.onSliderImageClick(bannerImageList[position % bannerImageList.size]) }
    return view
}

override fun isViewFromObject(view: View, `object`: Any): Boolean {
    return view === `object`
}

override fun getCount(): Int {
    return if (bannerImageList.size > 0) {
        Int.MAX_VALUE
    } else {
        0
    }
}

override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
    val viewPager = container as ViewPager
    val view = `object` as View
    viewPager.removeView(view)
}

interface SliderItemClickListener {
    fun onSliderImageClick(item: SliderImagesItem)
}

}

既然你提到你正在为 viewpager2 使用 recyclerview 适配器,你是否尝试过像在 recyclerview 中实现无限滚动时那样编写它。
基本上你需要在你的适配器的 getItemCount() 方法中 return Integer.MAX_VALUE 并且每当你在 onBindViewHolder 中你需要实际的项目位置总是使用 position % yourList.size() 。我还添加了 size > 0 检查以避免列表为空时崩溃,否则会抛出被零除的错误。

下面是一个示例适配器,您可以将其用作适配器的参考并检查它是否适合您。希望这有帮助。

public class SampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

private List<Sample> mSampleList;

public SampleAdapter(List<Sample> mSampleList) {
    this.mSampleList = mSampleList;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View viewCommonItems = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.demo_view, parent, false);
    ItemViewHolder commonHolders = new ItemViewHolder(viewCommonItems);
    return commonHolders;

}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    ItemViewHolder viewHolder = (ItemViewHolder) holder;
    if(mSampleList.size()>0) {
        Sample sample = mSampleList.get(position % mSampleList.size());
        Glide.with(viewHolder.itemView.getContext()).load(sample.getImage())
                .into(viewHolder.ivImage);
    }
}

@Override
public int getItemCount() {
    return Integer.MAX_VALUE;
}

public class ItemViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.iv_img)
    ImageView ivImage;
    public ItemViewHolder(@NonNull View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }
}

}