2011-11-23 32 views
13

Tôi đang sử dụng PagerAdapter để vuốt ngang để hiển thị các trang báo trong ứng dụng của tôi.Thực hiện cuộn tròn trong PagerAdapter

Hiện tại tôi muốn triển khai cuộn tròn trong ứng dụng này. Hiện tại, những gì tôi đã làm là whenever I am getting on last page I try to set the currentItem to first page tức là chức năng hoạt động cho trang cuối cùng đến trang đầu tiên, nhưng vấn đề là làm cách nào tôi có thể chuyển đến trang cuối cùng từ trang đầu tiên . Ở đây tôi đang dán mã của tôi liên quan đến pagerAdapter & onPageChangeListener: -

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

Ngoài ra PagerAdapter tức AwesomweAdapter trong trường hợp của tôi, cũng là như 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); 

    } 

Xin vui lòng cho tôi bất kỳ lời đề nghị/thay đổi trong mã của tôi (nếu có) cho nó. Cảm ơn trước.

+0

tôi thấy một số bộ chuyển đổi danh sách hình tròn trong các tài liệu .... –

+1

Những tài liệu đang nói về nó là Android hay một số khác. –

Trả lời

8

Tôi cũng cần có một ViewPager tròn. Đây là những gì tôi đã làm. Tôi giả sử bạn nhận được giá trị pageCount từ một nơi nào đó.

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

và đây là GestureDetector. sao chép từ here

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

} 
+0

: - Cảm ơn câu trả lời.Tôi sẽ thử điều này và trả lời bạn sớm. –

+0

@efeyc thanks !! pager.setOnTouchListener (..) đã giải quyết mọi vấn đề của tôi! – Beppe

+0

@efeyc ** MotionEvent e1 luôn luôn là null trong onFling() **. Có thể là do việc thực hiện vuốt của riêng trình xem trang. Bạn không phải đối mặt với vấn đề này? –

20

tôi có thể đạt được điều này bằng cách ghi đè onPageSelected phương pháp OnPageChangeListener. Hãy xem xét bạn có ba trang theo thứ tự này A<->B<->C. Mục tiêu là để đạt được C nếu chúng tôi di chuyển ngay từ A và tương tự để đạt được A nếu chúng tôi cuộn sang trái từ C.

Để làm điều này, định nghĩa của bạn để có 5 trang (3 + 2), và tổ chức các trang như sau:

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

Bây giờ trong phương pháp onPageSelected, kiểm tra và nếu vị trí nếu 0, hãy đổi thành 3 (getCount()-2) và nếu vị trí là 4 (getCount()-1), hãy thay đổi thành 1. Hãy chắc chắn để sử dụng phương pháp:

setCurrentItem(item, smoothScroll) 

Đây là mã hoàn chỉnh cho CircularPagerAdaptor Class:

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

Và đây là cách bạn có thể sử dụng nó:

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

hey u có thể vui lòng giải thích nó một cách chính xác hơn, nó đã thử nó nhưng không làm việc ra ngoài. – krisDrOid

+2

phần nào khó hiểu? Tóm lại, tôi thêm hai trang giả theo cả hai hướng, và khi chúng được chọn, tôi đã di chuyển vùng chọn đến vị trí thực của nó. – Z0lenDer

+0

Cảm ơn rất nhiều !!!!!!! – Chaitu

4

Mở rộng trên Z0lenDer Câu trả lời của bạn, khi sử dụng một số ViewPager thông thường, nơi bạn không cần phải giải phóng bộ nhớ cho mỗi chế độ xem được liên kết, nó sẽ hiệu quả hơn đối với lưu trữ các chế độ xem được tạo thay vì các ID bố cục. Điều này là cần thiết nếu muốn loại bỏ bất kỳ sự chậm trễ và nhấp nháy khi mục đang được chuyển.

Ngoài ra còn có vấn đề với hoạt ảnh khi sử dụng onPageSelected, vì nó không cho phép bản chiếu kết thúc trước khi thực hiện chuyển đổi.Cách duy nhất tôi tìm thấy để tránh điều này là chỉ thực hiện chuyển đổi khi trạng thái cuộn đã thay đổi thành SCROLL_STATE_IDLE và chỉ thiết lập mục hiện tại trong 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); 
       } 
      } 
     } 

    }); 
0

Hãy thử điều này

((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 

này nên được đặt bên

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

tôi đã sử dụng nó theo cách này, bố trí đoạn trong bộ chuyển đổi 0 > 1> 2> 3> 4> 5, 5 là giả

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

Vâng điều này đã giúp

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

    } 
} 

Nó được @ tobi_b của answer

Các vấn đề liên quan