【问题标题】:Infinite scrolling in viewpager2viewpager2 中的无限滚动
【发布时间】:2020-01-16 11:08:53
【问题描述】:

ViewPager2中如何实现无限滚动

因为此寻呼机中没有OnPageChangeListener()。 但是有setPageTransformer()Listener 每当我们改变页面时都会得到回调。

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

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

【问题讨论】:

  • 我正在返回位置视图

标签: java android android-viewpager2


【解决方案1】:

对于无限滚动,您不必自定义视图寻呼机。 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)
}

}

【讨论】:

    【解决方案2】:

    第一步:创建 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,所以用户可以前后滚动。

    【讨论】:

    • 是的,但我想要 recylerview。我得到了答案,感谢您的回复
    • @nikhillohar 很高兴为您提供帮助!
    • 非常感谢@KalpeshRupani !!,这有效,但给了我一个指向库行的无法追踪的内存泄漏......(FragmentViewHolder.itemView)。我在Java中使用创建片段的fragmentClass.newInstance() 方法......也许这就是我做错了。有什么建议吗??
    【解决方案3】:

    既然您提到您正在为 viewpager2 使用 recyclerview 适配器,您是否尝试过像在 recyclerview 中实现无限滚动一样编写它。
    基本上,您需要在适配器的 getItemCount() 方法中返回 Integer.MAX_VALUE ,并且无论何时在 onBindViewHolder 您需要实际项目位置时,始终使用 position % yourList.size() 。我还添加了size &gt; 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);
        }
    }
    

    }

    【讨论】:

    • 是的,正是我想要的
    【解决方案4】:

    您可以使用下面的代码

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

    【讨论】:

    • 你意识到这不是无限的,因为如果只有一个产品,那么它只会滚动一千次。
    【解决方案5】:

    试试下面的代码

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

    希望对你有帮助!

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-02
      • 2020-08-11
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 2012-01-13
      • 1970-01-01
      相关资源
      最近更新 更多