Infinite Scrolling Image Viewpager

Infinite Scrolling Image ViewPager

I had the same problem, but I was able to find a way to solve it - the code can be found on github.

If you copy the classes InfiniteViewPager and InfinitePagerAdapter into your project, you can achieve infinite (wrapped) scrolling with some small changes.

In your Activity, wrap your PagerAdapter with an InfinitePagerAdapter:

PagerAdapter adapter = new InfinitePagerAdapter(new ImagePagerAdapter(this, imageArra, stringArray));

Change the ViewPager in the activity XML to be an InfiniteViewPager:

<com.antonyt.infiniteviewpager.InfiniteViewPager 
android:id="@+id/myimagepager"
android:layout_width="match_parent"
android:layout_height="match_parent" />

You can rename the classes to whatever you want. This code only works if you have at least three pages (you have nine in your example code, so it will work fine for that).

Changing ViewPager to enable infinite page scrolling

Thank you for your answer Shereef.

I solved it a little bit differently.

I changed the code of the ViewPager class of the android support library. The method setCurrentItem(int)

changes the page with animation. This method calls an internal method that requires the index and a flag enabling smooth scrolling. This flag is boolean smoothScroll.
Extending this method with a second parameter boolean smoothScroll solved it for me.
Calling this method setCurrentItem(int index, boolean smoothScroll) allowed me to make it scroll indefinitely.

Here is a full example:

Please consider that only the center page is shown.
Moreover did I store the pages seperately, allowing me to handle them with more ease.

private class Page {
View page;
List<..> data;
}
// page for predecessor, current, and successor
Page[] pages = new Page[3];

mDayPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

@Override
public void onPageSelected(int position) {
}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

@Override
public void onPageScrollStateChanged(int state) {

if (state == ViewPager.SCROLL_STATE_IDLE) {

if (mFocusedPage == 0) {
// move some stuff from the
// center to the right here
moveStuff(pages[1], pages[2]);

// move stuff from the left to the center
moveStuff(pages[0], pages[1]);
// retrieve new stuff and insert it to the left page
insertStuff(pages[0]);
}
else if (mFocusedPage == 2) {

// move stuff from the center to the left page
moveStuff(pages[1], pages[0]);
// move stuff from the right to the center page
moveStuff(pages[2], pages[1]);
// retrieve stuff and insert it to the right page
insertStuff(pages[2]);
}

// go back to the center allowing to scroll indefinitely
mDayPager.setCurrentItem(1, false);
}
}
});

However, without Jon Willis Code I wouldn't have solved it myself.

EDIT: here is a blogpost about this:

Infinite scrolling in viewpager2

For infinite scrolling, you don't have to customise the view pager. The trick in the viewPager adapter. You can return Int.MAX value in getCount override method. The in the instantiateItem override function you can use item_position % item_size to get the actual item position. Code example is given below.

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

}

Circular scrolling with View Pager

Forget about ViewPager it's expensive, views is everything. You need three inflated views
let's say v1,v2,v3

I work with your provide git sample project, replace your HorizontalPaging with xml

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/scroller"
app:layout_constraintEnd_toEndOf="parent"
android:fillViewport="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<ImageView
android:id="@+id/v1"
android:layout_width="match_parent"
android:layout_height="300dp"
android:contentDescription="@null"
android:src="@drawable/slider_topup" />

<ImageView
android:id="@+id/v2"
android:layout_width="match_parent"
android:layout_height="300dp"
android:contentDescription="@null"
android:src="@drawable/slider_balance" />

<ImageView
android:id="@+id/v3"
android:layout_width="match_parent"
android:layout_height="300dp"
android:contentDescription="@null"
android:src="@drawable/slider_bundles" />

</RelativeLayout>

and add code to your onCreate

final View v1 = findViewById(R.id.v1);
final View v2 = findViewById(R.id.v2);
final View v3 = findViewById(R.id.v3);

//set initial state keep it sync with wheel at start
v1.setX(0);
v2.setX(screenSize);
v3.setX(2*screenSize);

circle.setOnAngleChangeListener(new NowCircle.OnAngleChangeListener() {
@Override
public void onAngleChange(float delta) {
float v1x = v1.getX() + (oneDegree * delta);
float v2x = v2.getX() + (oneDegree * delta);
float v3x = v3.getX() + (oneDegree * delta);

Log.d("dd","delta:"+delta+", v1x:"+v1x+", v2x:"+v2x +", v3x:"+v3x);

v1.setX(v1x);
v2.setX(v2x);
v3.setX(v3x);

if(delta > 0){

if (v1x >= 0 && v1x <= screenSize) {
v3.setX(-screenSize+v1x);
//update data here
}else if (v3x >= 0 && v3x <= screenSize){
v2.setX(-screenSize+v3x);
//update data here
}else {
v1.setX(-screenSize+v2x);
//update data here
}
}else {
if (v3x <= 0 && v3x >= -screenSize) {
v1.setX(screenSize+v3x);
//update data here
}else if(v1x <= 0 && v1x >= -screenSize){
v2.setX(screenSize+v1x);
//update data here
}else {
v3.setX(screenSize+v2x);
//update data here
}
}
}
});

animation is achieved, working fine.

Sample Image

You need to improve this and bind data with your custom views and create one separate manage class. I put my time into this. you know :)



Related Topics



Leave a reply



Submit