4

我们如何在 ViewPager2 中实现无限滚动

因为OnPageChangeListener()在这个寻呼机中没有。但是每当我们更改页面时,都会有setPageTransformer()监听器获取回调。

所以viewpager2问题的任何解决方案

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

4

5 回答 5

6

对于无限滚动,您不必自定义视图寻呼机。viewPager 适配器中的技巧。您可以在 getCount 覆盖方法中返回 Int.MAX 值。在 instanceiteItem 覆盖函数中,您可以使用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)
}

}

于 2020-01-27T06:14:27.500 回答
5

第 1 步:创建 EndlessScrollAdapter 类

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 从活动或片段调用

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

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

于 2020-01-24T06:30:36.440 回答
2

Since you mentioned you were using recyclerview adapter for viewpager2 have you tried writing it as you would while implementing infinite scroll in a recyclerview.
Basically you need to return Integer.MAX_VALUE in your adapter's getItemCount() method and whenever in onBindViewHolder you need actual item position always use position % yourList.size() . I've also added the size > 0 check in order to avoid crashes when list is empty and therefore this would otherwise throw a division by zero error.

Below is a sample adapter, you can use it as reference for your adapter and check if it works well for you. Hope this helps.

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);
    }
}

}

于 2020-01-27T09:47:45.457 回答
0

您可以使用下面的代码

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);
于 2020-01-16T11:22:58.517 回答
0

试试下面的代码

@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);
        }
    }
}

我希望这可以帮助你!

谢谢你。

于 2020-01-24T10:01:43.660 回答