Implementazione della scorrimento circolare in PagerAdapter

Sto usando PagerAdapter per lo spostamento orizzontale per mostrare pagine dei giornali nella mia app.

Attualmente voglio implementare lo scorrimento circolare in questa applicazione. Adesso quello che ho fatto è whenever I am getting on last page I try to set the currentItem to first page cioè quella funzionalità che funziona per l'ultima pagina alla prima pagina, ma il problema è che come posso andare all'ultima pagina dalla prima pagina. Qui incollo il mio codice relativo a pagerAdapter & onPageChangeListener: –

  • Come submit la visualizzazione alla schiena? Come controllare l'ordine z programmaticamente?
  • Invio di arrays di oggetti tramite serializzazione
  • Aiutare con un attributo personalizzato Visualizza all'interno di un progetto di libreria Android
  • registratore schermo con kitkat
  • Tema AppCompat personalizzato che non modifica l'icona di overflow sui dispositivi più vecchi
  • Esegui la ROM personalizzata sull'emulatore Android
  •   awesomeAdapter = new AwesomePagerAdapter(awesomePager); awesomePager.setAdapter(awesomeAdapter); awesomePager.setPageMargin(10); awesomePager.setOnPageChangeListener(new OnPageChangeListener() { int lastPosition; float posOffset = 0; @Override public void onPageSelected(int position) { viewerPage = position; CommonLogic.logMessage("Viewer Page:- "+ viewerPage, TAG, Log.VERBOSE); posOffset = 0; } @Override public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) { if (positionOffset == 0 && positionOffsetPixels == 0 && position != 0) { lastPosition = position; } posOffset -= positionOffset; CommonLogic.logMessage(" Position:- " + position + " Position Offset:- " + positionOffset + " Position Offset Variable:- " + posOffset + " Position Offset Pixels:- " + positionOffsetPixels + " Last Position " + lastPosition, TAG, Log.VERBOSE); CommonLogic.logMessage(" Last Position " + lastPosition, TAG, Log.VERBOSE); } @Override public void onPageScrollStateChanged(int state) { // To Detect the Last Page & This Sets it to first page.This working fine. if (state == ViewPager.SCROLL_STATE_DRAGGING && viewerPage == (uris.size() - 1)) { CommonLogic.logMessage("Scroll State Changed ", TAG,Log.VERBOSE); postDelayed(new Runnable() { @Override public void run() { awesomePager.setCurrentItem(0, true); } }, 200); } // I have also used this to detect whether the user is on first & try to move on last page,but it is not working well. else if (state == ViewPager.SCROLL_STATE_DRAGGING && (lastPosition == 0 || lastPosition == (uris.size() - 1)) && viewerPage == 0 && posOffset <= 0) { CommonLogic.logMessage( "Scroll State Changed ", TAG,Log.VERBOSE); postDelayed(new Runnable() { @Override public void run() { awesomePager.setCurrentItem((uris.size() - 1), true); } }, 200); } } } }); 

    Anche PagerAdapter cioè AwesomweAdapter nel mio caso, è anche come folllows: –

     private class AwesomePagerAdapter extends PagerAdapter { ViewPager pdfContainer; DocumentNewView documentNewView; CustomViewPager customViewPager; public AwesomePagerAdapter(CustomViewPager awesomePager) { this.customViewPager = awesomePager; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @Override public int getCount() { return uris.size(); } public DocumentNewView addViewAt(int position, DocumentNewView mainView) { CommonLogic.logMessage("Position of View:- " + position, TAG, Log.VERBOSE); pdfContainer.addView(mainView); return mainView; } /** * Create the page for the given position. The adapter is responsible * for adding the view to the container given here, although it only * must ensure this is done by the time it returns from * {@link #finishUpdate()}. * * @param container * The containing View in which the page will be shown. * @param position * The page position to be instantiated. * @return Returns an Object representing the new page. This does not * need to be a View, but can be some other container of the * page. */ @Override public Object instantiateItem(View collection, int position) { CommonLogic .logMessage("Instantiate Item Called ", TAG, Log.VERBOSE); documentNewView = new DocumentNewView(cxt, display, customViewPager); documentNewView.setPdfContext(new PdfContext()); CodecDocument codecDocument = documentNewView.open(uris .get(position)); documentNewView.renderDocument(codecDocument); documentNewView.setMaxZoom(4f); documentNewView.setVerticalScrollBarEnabled(true); codecDocument = null; this.pdfContainer = (ViewPager) collection; return addViewAt(position, documentNewView); } /** * Remove a page for the given position. The adapter is responsible for * removing the view from its container, although it only must ensure * this is done by the time it returns from {@link #finishUpdate()}. * * @param container * The containing View from which the page will be removed. * @param position * The page position to be removed. * @param object * The same object that was returned by * {@link #instantiateItem(View, int)}. */ @Override public void destroyItem(View collection, int position, Object view) { pdfContainer.removeView((DocumentNewView) view); } /** * Called when the a change in the shown pages has been completed. At * this point you must ensure that all of the pages have actually been * added or removed from the container as appropriate. * * @param container * The containing View which is displaying this adapter's * page views. */ @Override public void finishUpdate(View arg0) { CommonLogic.logMessage("Finish Update Called ", TAG, Log.VERBOSE); } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { } @Override public Parcelable saveState() { return null; } @Override public void startUpdate(View arg0) { CommonLogic.logMessage("State Update Called ", TAG, Log.VERBOSE); } @Override public boolean isViewFromObject(View view, Object object) { return view == ((DocumentNewView) object); } 

    Vi prego di fornirmi suggerimenti / modifiche nel mio codice (se del caso). Grazie in anticipo.

    6 Solutions collect form web for “Implementazione della scorrimento circolare in PagerAdapter”

    Potrei get questo da sostituire il metodo OnPageChangeListener di OnPageChangeListener . Considerate di avere tre pagine in questo ordine A<->B<->C Per raggiungere l'objective è raggiungere C se scorriamo a destra da A e allo stesso modo per raggiungere A se scorriamo a sinistra da C

    A tale scopo, definisci di avere 5 pagine (3 + 2) e organizza le pagine come segue:

    C <->A<->B<->C<-> A

    Ora nel metodo onPageSelected , controllare se la posizione se 0 , cambiarla su 3 ( getCount()-2 ) e se la posizione è 4 ( getCount()-1 ), modificacanvas a 1 . Assicurati di utilizzare il metodo:

     setCurrentItem(item, smoothScroll) 

    Ecco il codice completo per la class CircularPagerAdaptor :

     package zolender.adapters; import android.content.Context; import android.os.Parcelable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.LayoutInflater; import android.view.View; public class CircularPagerAdapter extends PagerAdapter{ private int[] pageIDsArray; private int count; public CircularPagerAdapter(final ViewPager pager, int... pageIDs) { super(); int actualNoOfIDs = pageIDs.length; count = actualNoOfIDs + 2; pageIDsArray = new int[count]; for (int i = 0; i < actualNoOfIDs; i++) { pageIDsArray[i + 1] = pageIDs[i]; } pageIDsArray[0] = pageIDs[actualNoOfIDs - 1]; pageIDsArray[count - 1] = pageIDs[0]; pager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { int pageCount = getCount(); if (position == 0){ pager.setCurrentItem(pageCount-2,false); } else if (position == pageCount-1){ pager.setCurrentItem(1,false); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // TODO Auto-generated method stub } @Override public void onPageScrollStateChanged(int state) { // TODO Auto-generated method stub } }); } public int getCount() { return count; } public Object instantiateItem(View container, int position) { LayoutInflater inflater = (LayoutInflater) container.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); int pageId = pageIDsArray[position]; View view = inflater.inflate(pageId, null); ((ViewPager) container).addView(view, 0); return view; } @Override public void destroyItem(View container, int position, Object object) { ((ViewPager) container).removeView((View) object); } @Override public void finishUpdate(View container) { // TODO Auto-generated method stub } @Override public boolean isViewFromObject(View view, Object object) { return view == ((View) object); } @Override public void restoreState(Parcelable state, ClassLoader loader) { // TODO Auto-generated method stub } @Override public Parcelable saveState() { // TODO Auto-generated method stub return null; } @Override public void startUpdate(View container) { // TODO Auto-generated method stub } } 

    Ecco come è ansible utilizzarlo:

     myPager = (ViewPager) findViewById(R.id.myfivepanelpager); PagerAdapter adapter = new CircularPagerAdapter(myPager, new int[]{R.layout.farleft, R.layout.left, R.layout.middle, R.layout.right, R.layout.farright}); myPager.setAdapter(adapter); myPager.setCurrentItem(3); 

    Ho anche bisogno di un ViewPager circolare. Questo è ciò che ho fatto. Suppongo che ottieni il valore di paginaCount da qualche parte.

     ... pager = (ViewPager) findViewById(R.id.pager); //Gesture detection final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector()); pager.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }); //pagelistener is just for getting selected page pager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { selectedPage = position; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { } }); 

    e qui è il GestureDetector. Copiato da qui

      class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { int SWIPE_MIN_DISTANCE = Utils.ConvertToPixel(mContext, 50); int SWIPE_MAX_OFF_PATH = Utils.ConvertToPixel(mContext, 250); int SWIPE_THRESHOLD_VELOCITY = Utils.ConvertToPixel(mContext, 200); try { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // right to left swipe if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY && selectedPage == (pageCount - 1)) { pager.setCurrentItem(0); return true; } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY && selectedPage == 0) { pager.setCurrentItem(pageCount - 1); return true; } } catch (Exception e) { // nothing } return false; } } 

    Espandendo la risposta di Z0lenDer , quando si utilizza un normale ViewPager cui non è necessario liberare la memory per each vista associata, è più efficiente memorizzare le viste create anziché gli ID layout. Ciò è necessario se si desidera eliminare qualsiasi ritardo e sfarfallio quando l'elemento viene commutato.

    C'è anche un problema con l'animation quando si utilizza onPageSelected , in quanto non consente che la diapositiva finisca prima di eseguire l'interruttore. L'unico modo che ho trovato per evitare questo è quello di eseguire l'interruttore solo una volta che lo stato di scorrimento è stato modificato in SCROLL_STATE_IDLE e solo impostando l'elemento corrente in onPageSelected .

     private int currentPage = 0; 

      pager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { currentPage = position; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { // TODO Auto-generated method stub Log.d(TAG, "onPageScrollStateChanged: " + state); if (state == ViewPager.SCROLL_STATE_IDLE) { int pageCount = getCount(); if (currentPage == 0){ pager.setCurrentItem(pageCount-2,false); } else if (currentPage == pageCount-1){ pager.setCurrentItem(1,false); } } } }); 

    Prova questo

     ((ViewPager) container) .setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { Log.i("TAG", "pos::" + position); } @Override public void onPageScrollStateChanged(int state) { // TODO Auto-generated method stub int currentPage = pager.getCurrentItem(); Log.i("TAG", "currentPage::" + currentPage); Log.i("TAG", "currentState::" + currentState); Log.i("TAG", "previousState::" + previousState); if (currentPage == 4 || currentPage == 0) { previousState = currentState; currentState = state; if (previousState == 1 && currentState == 0) { pager.setCurrentItem(currentPage == 0 ? 4 : 0); } } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } }); return 

    Questo dovrebbe essere collocato all'interno

      @Override public Object instantiateItem(final View container, int position) {} 

    Ho usato in questo modo, layout di frammenti nell'adattatore 0> 1> 2> 3> 4> 5, 0 & 5 sono fittizi

      viewPager.setAdapter(adapter); viewPager.setCurrentItem(1, false); //going to page 1; final int[] pagePosition = new int[1]; viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { pagePosition[0] = position; } @Override public void onPageScrollStateChanged(int state) { //state changes from 2 to 0 during a swipe if (state == 0 && pagePosition[0] == 0){ viewPager.setCurrentItem(4, false); } else if (state == 0 && pagePosition[0] == 5){ viewPager.setCurrentItem(1, false); } } }); 

    Beh, questo ha aiutato

      private class CircularViewPagerHandler implements ViewPager.OnPageChangeListener { private ViewPager mViewPager; private int mCurrentPosition; private int mScrollState; private int mPreviousPosition; public CircularViewPagerHandler(final ViewPager viewPager) { mViewPager = viewPager; } @Override public void onPageSelected(final int position) { mCurrentPosition = position; mPreviousPosition = position-1; } @Override public void onPageScrollStateChanged(final int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { setNextItemIfNeeded(); } mScrollState = state; } private void setNextItemIfNeeded() { if (!isScrollStateSettling()) { handleSetNextItem(); } } private boolean isScrollStateSettling() { return mScrollState == ViewPager.SCROLL_STATE_SETTLING; //indicated page is settling to it's final position } private void handleSetNextItem() { final int lastPosition = mViewPager.getAdapter().getCount() - 1; if (mCurrentPosition == 0) { mViewPager.setCurrentItem(lastPosition,false); } else if (mCurrentPosition == lastPosition) { mViewPager.setCurrentItem(0, false); } } @Override public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) { } } 

    Era la risposta di @ tobi_b

    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.