簡體   English   中英

在viewpager2中無限滾動

[英]Infinite scrolling in viewpager2

我們如何在 ViewPager2 中實現無限滾動

因為在這個尋呼機中沒有OnPageChangeListener() 但是有setPageTransformer()偵聽器,每當我們更改頁面時都會收到回調。

因此,viewpager2 問題的任何解決方案

注意:我正在為 viewpager2 使用 recyclerview 適配器

第 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 從 Activity 或 Fragment 調用

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

從字面上看,這不是無窮無盡的,但從用戶的角度來看,它是無窮無盡的,因為他永遠不會到達邊緣。 ViewPager2的長度是Int.MAX_VALUE ,起始位置是Int.MAX_VALUE/2這樣用戶可以向前和向后滾動。

對於無限滾動,您不必自定義視圖尋呼機。 viewPager 適配器中的技巧。 您可以在 getCount 覆蓋方法中返回 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()方法中返回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);
    }
}

}

您可以使用下面的代碼

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

試試下面的代碼

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

我希望這可以幫助你!

謝謝你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM