The principle of Android picture cycle control

Posted by coreyk67 on Sun, 05 Jan 2020 22:30:00 +0100

The picture carousel control is usually composed of ViewPager and indicator.
Because ViewPager does not support circular page flipping, you need to handle it yourself. When the ViewPager cannot slide forward or backward in the first and last item, we can add an item at the beginning and end of the original list. Add the first item as the last item of the original list, and the last item as the first item of the original list. And when the ViewPager switches to the boundary page, silently changes to the second page or the penultimate page, you can scroll and switch. Use ViewPage.setCurrentItem(int item, boolean smoothScroll) to switch pages immediately.

Index location Original list ViewPager display list
0 A B
1 B A
2 B
3 A

Main code:

 //Number of carousels
 private int count;
 //ViewPager current item
 private int mCurrentItem;

private void setImageList(List<?> imageUrls) {
       ...
       for (int i = 0; i <= count + 1; i ++) {
           ...
           Object path;
           if (i == 0) {
               path = imageUrls.get(count - 1);
           } else if (i == count + 1) {
               path = imageUrls.get(0);
           } else {
               path = imageUrls.get(i - 1);
           }
           ...
       }
   }

/**
* Monitor ViewPager scroll status
*/
@Override
 public void onPageScrollStateChanged(int state) {
     Log.i(tag, "onPageScrollStateChanged state=" + state);
     if (mOnPageChangeListener != null) {
         mOnPageChangeListener.onPageScrollStateChanged(state);
     }
     switch (state) {
         case ViewPager.SCROLL_STATE_IDLE://No operation
             setCurrentPageSilence();
             break;
         case ViewPager.SCROLL_STATE_DRAGGING://Start dragging
             setCurrentPageSilence();
             break;
         case ViewPager.SCROLL_STATE_SETTLING://Drag final position
             break;
     }
 }

/**
  * Switch pages quietly
  */
  private void setCurrentPageSilence() {
      if (mCurrentItem == 0) {
          mViewPager.setCurrentItem(count, false);
      } else if(mCurrentItem == count + 1) {
          mViewPager.setCurrentItem(1, false);
      }
  }

In addition, the automatic round robin is realized by the Handler submitting the delayed task, which switches to the next page when the task is running. Also silently changes to the second page when the last page is rotated.

/**
     * Backward rotation task
     */
    private Runnable mPlayTask = new Runnable() {
        @Override
        public void run() {
            if (mIsAutoPlay) {
                if (mCurrentItem == count + 1) {
                    mCurrentItem = 1;
                    setCurrentPageSilence();
                    mHandler.post(this);
                } else {
                    mCurrentItem += 1;
                    //next page
                    mViewPager.setCurrentItem(mCurrentItem);
                    mHandler.postDelayed(this, mDelayTime);
                }
            }
        }
    };

Note that the Handler reference is not released, which causes memory leak.