wake-up-neo.com

Ändern Sie ViewPager, um das unendliche Scrollen zu ermöglichen

Jon Willis hat gepostet, wie man mit seinem Code ein unendliches Scrollen aktivieren kann .. Dort sagte er, dass er einige Änderungen in der ViewPager-Klasse in der Android-Support-Bibliothek vorgenommen hat. Welche Änderungen wurden vorgenommen und wie kann die Bibliothek mit der ViewPager-Änderung "neu kompiliert" werden?

41
thehayro

Vielen Dank für Ihre Antwort, Shereef.

Ich habe es etwas anders gelöst.

Ich habe den Code der ViewPager-Klasse der Android-Support-Bibliothek geändert. Die Methode setCurrentItem(int)

wechselt die Seite mit Animation. Diese Methode ruft eine interne Methode auf, für die der Index und ein Flag erforderlich sind, um ein reibungsloses Scrollen zu ermöglichen. Dieses Flag ist boolean smoothScroll. Durch das Erweitern dieser Methode um einen zweiten Parameter boolean smoothScroll wurde es für mich gelöst. Durch das Aufrufen dieser Methode setCurrentItem(int index, boolean smoothScroll) konnte ich es unbegrenzt zum Scrollen bringen.

Hier ist ein vollständiges Beispiel:

Bitte beachten Sie, dass nur die mittlere Seite angezeigt wird .. Außerdem habe ich die Seiten separat gespeichert, sodass ich sie einfacher handhaben kann.

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

Ohne Jon Willis Code hätte ich es jedoch nicht selbst gelöst. 

EDIT: hier ist ein blogpost dazu: 

32
thehayro

Ich habe dieses Problem sehr einfach gelöst, indem ich einen kleinen Hack im Adapter benutzte. Hier ist mein Code:

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


    public MyPagerAdapter(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(); // use modulo for infinite cycling
            return MyFragment.newInstance(mProducts.get(position));
        }
        else
        {
            return MyFragment.newInstance(null);
        }
    }


    @Override
    public int getCount()
    {
        if (mProducts != null && mProducts.size() > 0)
        {
            return mProducts.size()*LOOPS_COUNT; // simulate infinite by big number of products
        }
        else
        {
            return 1;
        }
    }
} 

Und dann setzen wir im ViewPager die aktuelle Seite in die Mitte:

mAdapter = new MyPagerAdapter(getSupportFragmentManager(), mProducts);
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mViewPager.getChildCount() * MyPagerAdapter.LOOPS_COUNT / 2, false); // set current item in the adapter to middle
36
petrnohejl

Unbegrenzter View-Pager durch Überschreiben von 4 Adaptermethoden in Ihrer vorhandenen Adapterklasse

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

    @Override
    public CharSequence getPageTitle(int position) {
        String title = mTitleList.get(position % mActualTitleListSize);
        return title;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        int virtualPosition = position % mActualTitleListSize;
        return super.instantiateItem(container, virtualPosition);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        int virtualPosition = position % mActualTitleListSize;
        super.destroyItem(container, virtualPosition, object);
    }
30

Sie müssen sich nur das Beispiel ansehen hier

Sie werden feststellen, dass in Zeile 295 die Seite immer auf 1 gesetzt ist, so dass sie scrollbar ist Und die Anzahl der Seiten in der getCount()-Methode 3 ist.

Dies sind die beiden wichtigsten Dinge, die Sie ändern müssen. Der Rest ist Ihre Logik und Sie können anders damit umgehen.

Erstellen Sie einfach einen persönlichen Zähler, der die tatsächliche Seite zählt, auf der Sie sich befinden, da die Position nicht mehr verwendbar ist, wenn Sie die aktuelle Seite immer auf 1 in Zeile 295 setzen.

p.s. Dieser Code gehört nicht mir, er wurde in der Frage angegeben, auf die Sie in Ihrer Frage verlinkt haben

9
Shereef Marzouk

Tatsächlich habe ich mir die verschiedenen Möglichkeiten angesehen, diese "unendliche" Paginierung durchzuführen, und obwohl der menschliche Zeitbegriff unendlich ist (obwohl wir eine Vorstellung von Anfang und Ende der Zeit haben), beschäftigen sich Computer damit im diskreten. Es gibt eine minimale und maximale Zeit (die im Laufe der Zeit eingestellt werden kann, erinnern Sie sich an die Basis der Y2K-Angst?). 

In dieser Diskussion geht es jedenfalls darum, dass es ausreicht, einen relativ unendlichen Datumsbereich durch einen tatsächlich endlichen Datumsbereich zu unterstützen. Ein gutes Beispiel dafür ist die CalendarView-Implementierung des Android-Frameworks und die WeeksAdapter darin. Das voreingestellte minimale Datum ist in 1900 und das voreingestellte maximale Datum ist in 2100, dies sollte 99% der Kalendernutzung eines jeden innerhalb eines 10-Jahres-Radius um den heutigen Tag problemlos erfassen. 

Was sie in ihrer Implementierung (auf Wochen konzentriert) tun, ist die Anzahl der Wochen zwischen dem minimalen und dem maximalen Datum zu berechnen. Dies ist die Anzahl der Seiten im Pager. Denken Sie daran, dass der Pager nicht alle Seiten gleichzeitig verwalten muss (setOffscreenPageLimit(int)). Er muss lediglich die Seite basierend auf der Seitennummer (oder dem Index/der Position) erstellen können. In diesem Fall ist der Index die Anzahl der Wochen, ab denen die Woche vom Mindestdatum entfernt ist. Bei diesem Ansatz müssen Sie nur das minimale Datum und die Anzahl der Seiten (Abstand zum maximalen Datum) beibehalten. Dann können Sie für jede Seite die Woche berechnen, die dieser Seite zugeordnet ist. Kein Tanzen um die Tatsache herum, dass ViewPager keine Schleife unterstützt (a.k.a eine unendliche Paginierung), und der Versuch, es zu zwingen, sich so zu verhalten, dass es sich so verhält, als könnte es unendlich scrollen.

new FragmentStatePagerAdapter(getFragmentManager()) {
    @Override
    public Fragment getItem(int index) {
        final Bundle arguments = new Bundle(getArguments());
        final Calendar temp_calendar = Calendar.getInstance();
        temp_calendar.setTimeInMillis(_minimum_date.getTimeInMillis());
        temp_calendar.setFirstDayOfWeek(_calendar.getStartOfWeek());
        temp_calendar.add(Calendar.WEEK_OF_YEAR, index);
        // Moves to the first day of this week
        temp_calendar.add(Calendar.DAY_OF_YEAR,
                -UiUtils.modulus(temp_calendar.get(Calendar.DAY_OF_WEEK) - temp_calendar.getFirstDayOfWeek(),
                7));
        arguments.putLong(KEY_DATE, temp_calendar.getTimeInMillis());
        return Fragment.instantiate(getActivity(), WeekDaysFragment.class.getName(), arguments);
    }

    @Override
    public int getCount() {
        return _total_number_of_weeks;
    }
};

Dann kann WeekDaysFragment leicht die Woche anzeigen, die an dem in den Argumenten übergebenen Datum beginnt.

Alternativ scheint es, dass einige Versionen der Kalender-App auf Android eine ViewSwitcher verwenden (was bedeutet, dass es nur 2 Seiten gibt, die Sie sehen und die verborgene Seite). Sie ändert dann die Übergangsanimation basierend auf der Art und Weise, in der der Benutzer gewischt hat, und rendert die nächste/vorherige Seite entsprechend. Auf diese Weise erhalten Sie eine unendliche Paginierung, weil Sie nur unendlich oft zwischen zwei Seiten wechseln. Dies erfordert jedoch die Verwendung einer View für die Seite. Dies ist der Weg, auf dem ich mich beim ersten Ansatz befand.

Wenn Sie eine "unendliche Paginierung" wünschen, liegt dies wahrscheinlich daran, dass Ihre Seiten auf Datums- oder Zeitangaben basieren. Wenn dies der Fall ist, sollten Sie eine endliche Zeitspanne verwenden, die relativ unbegrenzt ist. So wird zum Beispiel CalendarView implementiert. Oder Sie können den ViewSwitcher-Ansatz verwenden. Der Vorteil dieser beiden Ansätze ist, dass keine der beiden Optionen etwas ungewöhnliches mit der Variablen ViewSwitcher oder ViewPager ist, und dass keine Tricks oder Neuimplementierungen erforderlich sind, um sie dazu zu bringen, sich unendlich zu benehmen (ViewSwitcher ist bereits dafür gedacht, zwischen Ansichten unendlich zu wechseln, aber ViewPager ist dafür gedacht Arbeit an einer endlichen, aber nicht unbedingt konstanten Seitengruppe).

5
Dandre Allison

unendliches Slider-Adapter-Skelett basierend auf vorherigen Proben

einige kritische Fragen:

  • beachten Sie die ursprüngliche (relative) Position in der Seitenansicht (in Beispiel verwendetes Tag). Wir werden also diese Position betrachten, um die relative Position der Ansicht zu definieren. Andernfalls ist die untergeordnete Reihenfolge im Pager gemischt
  • muss erstmal absolute ansicht in den adapter füllen. (der Rest der Zeiten ist diese Füllung ungültig.) Es wurde keine Möglichkeit gefunden, die Füllung aus dem Pagerhandler zu erzwingen. Die absolute Ansicht der Ruhezeiten wird vom Pagerhandler mit korrekten Werten überschrieben.
  • wenn Seiten schnell verschoben werden, wird die Seite (tatsächlich links) nicht vom Pagerhandler ausgefüllt. Momentan keine Problemumgehung, verwenden Sie einfach eine leere Ansicht. Wenn das Ziehen angehalten wird, werden die tatsächlichen Werte gefüllt. upd: Schnelle Problemumgehung: Deaktivieren Sie das destroyItem des Adapters.

sie können sich das Logcat ansehen, um zu verstehen, was in diesem Beispiel passiert

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:id="@+id/calendar_text"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:textSize="20sp"
        Android:padding="5dp"
        Android:layout_gravity="center_horizontal"
        Android:text="Text Text Text"
    />

</RelativeLayout>

Und dann:

public class ActivityCalendar extends Activity
{
    public class CalendarAdapter extends PagerAdapter
    {
        @Override
        public int getCount()
        {
            return 3;
        }

        @Override
        public boolean isViewFromObject(View view, Object object)
        {
            return view == ((RelativeLayout) object);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position)
        {
            LayoutInflater inflater = (LayoutInflater)ActivityCalendar.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View viewLayout = inflater.inflate(R.layout.layout_calendar, container, false);
            viewLayout.setTag(new Integer(position));

            //TextView tv = (TextView) viewLayout.findViewById(R.id.calendar_text);
            //tv.setText(String.format("Text Text Text relative: %d", position));

            if (!ActivityCalendar.this.scrolledOnce)
            {
                // fill here only first time, the rest will be overriden in pager scroll handler
                switch (position)
                {
                    case 0:
                        ActivityCalendar.this.setPageContent(viewLayout, globalPosition - 1);
                        break;
                    case 1:
                        ActivityCalendar.this.setPageContent(viewLayout, globalPosition);
                        break;
                    case 2:
                        ActivityCalendar.this.setPageContent(viewLayout, globalPosition + 1);
                        break;
                }
            }

            ((ViewPager) container).addView(viewLayout);

            //Log.i("instantiateItem", String.format("position = %d", position));

            return viewLayout;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object)
        {
            ((ViewPager) container).removeView((RelativeLayout) object);

            //Log.i("destroyItem", String.format("position = %d", position));
        }
    }

    public void setPageContent(View viewLayout, int globalPosition)
    {
        if (viewLayout == null)
            return;
        TextView tv = (TextView) viewLayout.findViewById(R.id.calendar_text);
        tv.setText(String.format("Text Text Text global %d", globalPosition));
    }

    private boolean scrolledOnce = false;
    private int focusedPage = 0;
    private int globalPosition = 0;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calendar);

        final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);

        viewPager.setOnPageChangeListener(new OnPageChangeListener()
        {
            @Override
            public void onPageSelected(int position)
            {
                focusedPage = position;
                // actual page change only when position == 1
                if (position == 1)
                    setTitle(String.format("relative: %d, global: %d", position, globalPosition));
                Log.i("onPageSelected", String.format("focusedPage/position = %d, globalPosition = %d", position, globalPosition));
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
            {
                //Log.i("onPageScrolled", String.format("position = %d, positionOffset = %f", position, positionOffset));
            }

            @Override
            public void onPageScrollStateChanged(int state)
            {
                Log.i("onPageScrollStateChanged", String.format("state = %d, focusedPage = %d", state, focusedPage));
                if (state == ViewPager.SCROLL_STATE_IDLE)
                {
                    if (focusedPage == 0)
                        globalPosition--;
                    else if (focusedPage == 2)
                        globalPosition++;

                    scrolledOnce = true;

                    for (int i = 0; i < viewPager.getChildCount(); i++)
                    {
                        final View v = viewPager.getChildAt(i);
                        if (v == null)
                            continue;

                        // reveal correct child position
                        Integer tag = (Integer)v.getTag();
                        if (tag == null)
                            continue;

                        switch (tag.intValue())
                        {
                            case 0:
                                setPageContent(v, globalPosition - 1);
                                break;
                            case 1:
                                setPageContent(v, globalPosition);
                                break;
                            case 2:
                                setPageContent(v, globalPosition + 1);
                                break;
                        }
                    }

                    Log.i("onPageScrollStateChanged", String.format("globalPosition = %d", globalPosition));

                    viewPager.setCurrentItem(1, false);
                }
            }
        });

        CalendarAdapter calendarAdapter = this.new CalendarAdapter();
        viewPager.setAdapter(calendarAdapter);

        // center item
        viewPager.setCurrentItem(1, false);
    }
}
2
Dmitry Bryliuk

Sein gehackt von CustomPagerAdapter :

MainActivity.Java :

import Android.content.Context;
import Android.os.Handler;
import Android.os.Parcelable;
import Android.support.v4.app.FragmentPagerAdapter;
import Android.support.v4.app.FragmentStatePagerAdapter;
import Android.support.v4.view.PagerAdapter;
import Android.support.v4.view.ViewPager;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.LinearLayout;
import Android.widget.TextView;
import Java.util.ArrayList;
import Java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<String> numberList = new ArrayList<String>();
    private CustomPagerAdapter mCustomPagerAdapter;
    private ViewPager mViewPager;
    private Handler handler;
    private Runnable runnable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        numberList.clear();
        for (int i = 0; i < 10; i++) {
        numberList.add(""+i);
        }

        mViewPager = (ViewPager)findViewById(R.id.pager);
        mCustomPagerAdapter = new CustomPagerAdapter(MainActivity.this);
        EndlessPagerAdapter mAdapater = new EndlessPagerAdapter(mCustomPagerAdapter);
        mViewPager.setAdapter(mAdapater);


        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                int modulo = position%numberList.size();
                Log.i("Current ViewPager View's Position", ""+modulo);

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

        handler = new Handler();
        runnable = new Runnable() {
            @Override
            public void run() {

                mViewPager.setCurrentItem(mViewPager.getCurrentItem()+1);
                handler.postDelayed(runnable, 1000);
            }
        };

        handler.post(runnable);

    }

    @Override
    protected void onDestroy() {
        if(handler!=null){
            handler.removeCallbacks(runnable);
        }
        super.onDestroy();
    }

    private class CustomPagerAdapter extends PagerAdapter {

        Context mContext;
        LayoutInflater mLayoutInflater;

        public CustomPagerAdapter(Context context) {
            mContext = context;
            mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public int getCount() {
            return numberList.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == ((LinearLayout) object);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View itemView = mLayoutInflater.inflate(R.layout.row_item_viewpager, container, false);

            TextView textView = (TextView) itemView.findViewById(R.id.txtItem);
            textView.setText(numberList.get(position));
            container.addView(itemView);
            return itemView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((LinearLayout) object);
        }
    }

    private class EndlessPagerAdapter extends PagerAdapter {

        private static final String TAG = "EndlessPagerAdapter";
        private static final boolean DEBUG = false;

        private final PagerAdapter mPagerAdapter;

        EndlessPagerAdapter(PagerAdapter pagerAdapter) {
            if (pagerAdapter == null) {
                throw new IllegalArgumentException("Did you forget initialize PagerAdapter?");
            }
            if ((pagerAdapter instanceof FragmentPagerAdapter || pagerAdapter instanceof FragmentStatePagerAdapter) && pagerAdapter.getCount() < 3) {
                throw new IllegalArgumentException("When you use FragmentPagerAdapter or FragmentStatePagerAdapter, it only supports >= 3 pages.");
            }
            mPagerAdapter = pagerAdapter;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            if (DEBUG) Log.d(TAG, "Destroy: " + getVirtualPosition(position));
            mPagerAdapter.destroyItem(container, getVirtualPosition(position), object);

            if (mPagerAdapter.getCount() < 4) {
                mPagerAdapter.instantiateItem(container, getVirtualPosition(position));
            }
        }

        @Override
        public void finishUpdate(ViewGroup container) {
            mPagerAdapter.finishUpdate(container);
        }

        @Override
        public int getCount() {
            return Integer.MAX_VALUE; // this is the magic that we can scroll infinitely.
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mPagerAdapter.getPageTitle(getVirtualPosition(position));
        }

        @Override
        public float getPageWidth(int position) {
            return mPagerAdapter.getPageWidth(getVirtualPosition(position));
        }

        @Override
        public boolean isViewFromObject(View view, Object o) {
            return mPagerAdapter.isViewFromObject(view, o);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (DEBUG) Log.d(TAG, "Instantiate: " + getVirtualPosition(position));
            return mPagerAdapter.instantiateItem(container, getVirtualPosition(position));
        }

        @Override
        public Parcelable saveState() {
            return mPagerAdapter.saveState();
        }

        @Override
        public void restoreState(Parcelable state, ClassLoader loader) {
            mPagerAdapter.restoreState(state, loader);
        }

        @Override
        public void startUpdate(ViewGroup container) {
            mPagerAdapter.startUpdate(container);
        }

        int getVirtualPosition(int realPosition) {
            return realPosition % mPagerAdapter.getCount();
        }

        PagerAdapter getPagerAdapter() {
            return mPagerAdapter;
        }

    }
}

activity_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools" Android:layout_width="match_parent"
    Android:layout_height="match_parent" Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin"
    Android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Android.support.v4.view.ViewPager xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:id="@+id/pager"
        Android:layout_width="match_parent"
        Android:layout_height="180dp">
    </Android.support.v4.view.ViewPager>

</RelativeLayout>

row_item_viewpager.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent" Android:layout_height="match_parent"
    Android:gravity="center">

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:id="@+id/txtItem"
        Android:textAppearance="@Android:style/TextAppearance.Large"/>

</LinearLayout>

Erledigt

2
Hiren Patel

Für das unendliche Scrollen mit Tagen ist es wichtig, dass Sie das gute Fragment im Pager haben. Deshalb schrieb ich meine Antwort auf dieser Seite ( Viewpager in Android, um zwischen Tagen endlos zu wechseln )

Es funktioniert sehr gut! Die obigen Antworten haben für mich nicht funktioniert, da ich wollte, dass es funktioniert.

0

Basierend auf https://github.com/antonyt/InfiniteViewPager habe ich das aufgeschrieben, was gut funktioniert:

class InfiniteViewPager @JvmOverloads constructor(
  context: Context,
  attrs: AttributeSet? = null
) : ViewPager(context, attrs) {
  // Allow for 100 back cycles from the beginning.
  // This should be enough to create an illusion of infinity.
  // Warning: scrolling to very high values (1,000,000+) results in strange drawing behaviour.
  private val offsetAmount get() = if (adapter?.count == 0) 0 else (adapter as InfinitePagerAdapter).realCount * 100

  override fun setAdapter(adapter: PagerAdapter?) {
    super.setAdapter(if (adapter == null) null else InfinitePagerAdapter(adapter))
    currentItem = 0
  }

  override fun setCurrentItem(item: Int) = setCurrentItem(item, false)

  override fun setCurrentItem(item: Int, smoothScroll: Boolean) {
    val adapterCount = adapter?.count

    if (adapterCount == null || adapterCount == 0) {
      super.setCurrentItem(item, smoothScroll)
    } else {
      super.setCurrentItem(offsetAmount + item % adapterCount, smoothScroll)
    }
  }

  override fun getCurrentItem(): Int {
    val adapterCount = adapter?.count

    return if (adapterCount == null || adapterCount == 0) {
      super.getCurrentItem()
    } else {
      val position = super.getCurrentItem()
      position % (adapter as InfinitePagerAdapter).realCount
    }
  }

  fun animateForward() {
    super.setCurrentItem(super.getCurrentItem() + 1, true)
  }

  fun animateBackwards() {
    super.setCurrentItem(super.getCurrentItem() - 1, true)
  }

  internal class InfinitePagerAdapter(private val adapter: PagerAdapter) : PagerAdapter() {
    internal val realCount: Int get() = adapter.count

    override fun getCount() = if (realCount == 0) 0 else Integer.MAX_VALUE

    override fun instantiateItem(container: ViewGroup, position: Int) = adapter.instantiateItem(container, position % realCount)

    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) = adapter.destroyItem(container, position % realCount, `object`)

    override fun finishUpdate(container: ViewGroup) = adapter.finishUpdate(container)

    override fun isViewFromObject(view: View, `object`: Any) = adapter.isViewFromObject(view, `object`)

    override fun restoreState(bundle: Parcelable?, classLoader: ClassLoader?) = adapter.restoreState(bundle, classLoader)

    override fun saveState(): Parcelable? = adapter.saveState()

    override fun startUpdate(container: ViewGroup) = adapter.startUpdate(container)

    override fun getPageTitle(position: Int) = adapter.getPageTitle(position % realCount)

    override fun getPageWidth(position: Int) = adapter.getPageWidth(position)

    override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) = adapter.setPrimaryItem(container, position, `object`)

    override fun unregisterDataSetObserver(observer: DataSetObserver) = adapter.unregisterDataSetObserver(observer)

    override fun registerDataSetObserver(observer: DataSetObserver) = adapter.registerDataSetObserver(observer)

    override fun notifyDataSetChanged() = adapter.notifyDataSetChanged()

    override fun getItemPosition(`object`: Any) = adapter.getItemPosition(`object`)
  }
}

Um es zu konsumieren, ändern Sie einfach Ihren ViewPager in InfiniteViewPager und das ist alles, was Sie ändern müssen.

0
Niklas

Ich habe eine Bibliothek erstellt, die ViewPager, PagerAdapter (oder FragmentStatePagerAdapter) und optionales TabLayout unendlich scrollen lässt.

https://github.com/memorex386/infinite-scroll-viewpager-w-tabs

0
Brad