无限循环的ViewPager

目前情况

在不修改源码的情况下,当ViewPager滑动到最后一个item的时候,他就无法再往右滑动;当ViewPager滑动到第一个item的时候,他也无法再往前滑动。(以上全是废话)

设想

我们可以这样想,当滑动最后一个的时候,我们让他跳转到第一个,这样他就可以继续往后滑动了,这样做行程了我们想要的循环滑动。

如果这样作,虽然功能上是循环了,但是实际显示的时候会在最后一个和第一个之间自动跳转。

优化

我们可以在原来的链表中首尾各增加一个假的item,用多余的两个item来作跳转的动作,这样就可以避免出现自动跳转的错误画面了。请看下面演示。

我们要显示的是下面A、B、C画面,位置分别是0、1、2.

 

 

 

 

实际上,我们添加数据的时候,多添加了2个。在位置0添加了最后一个界面C,在位置4添加了第一个界面A。

 

当界面滑动到位置3的时候,他还可以往右滑动,这样给人的感觉就是循环的。但,当滑动到位置4的时候,他右边没有了,这样岂不是露馅了?所以,当滑动到位置4的时候,立刻跳转到位置1。因为他们是同样的数据,所以从显示效果是看不出跳转了的,这样实际上我们就变成了位置1,这样就又可以继续往右滑动了。

重复上面条件的判断,这样就实现了往右的循环,往左也是同样的道理。

代码分析

在onPageSelected里面做条件判断,在onPageScrollStateChanged里面做跳转。关键代码如下:

初始化,首尾各增加一个item。

 

  1. // 增加第1个界面,实际上他显示的是最后一个界面  
  2. addTextView(POINT_LENGTH - 1);  
  3. // 增加实际显示的2、3、4界面  
  4. for (int i = 0; i < 3; i++) {  
  5. addTextView(i);  
  6. addPoint(i);  
  7. }  
  8. // 增加最后的第5个界面,实际上他显示的是第一个界面  
  9. addTextView(0);  

 

条件判断:

 

  1. @Override  
  2. public void onPageSelected(int pPosition) {  
  3.     mIsChanged = true;  
  4.     if (pPosition > POINT_LENGTH) {  
  5.         mCurrentPagePosition = FIRST_ITEM_INDEX;  
  6.     } else if (pPosition < FIRST_ITEM_INDEX) {  
  7.         mCurrentPagePosition = POINT_LENGTH;  
  8.     } else {  
  9.         mCurrentPagePosition = pPosition;  
  10.     }  
  11.     Log.i(TAG,"当前的位置是"+mCurrentPagePosition);  
  12.     setCurrentDot(mCurrentPagePosition);  
  13. }  

 

跳转:

 

  1. @Override  
  2. public void onPageScrollStateChanged(int pState) {  
  3.     if (ViewPager.SCROLL_STATE_IDLE == pState) {  
  4.         if (mIsChanged) {  
  5.             mIsChanged = false;  
  6.             mViewPager.setCurrentItem(mCurrentPagePosition, false);  
  7.         }  
  8.     }  
  9. }  

 

完整的逻辑如下:

 

  1. package com.ahacool.circleviewpager;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.support.v4.view.PagerAdapter;  
  8. import android.support.v4.view.ViewPager;  
  9. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  10. import android.util.Log;  
  11. import android.view.Gravity;  
  12. import android.view.View;  
  13. import android.view.ViewGroup;  
  14. import android.widget.ImageView;  
  15. import android.widget.LinearLayout.LayoutParams;  
  16. import android.widget.TextView;  
  17.   
  18. /** 
  19.  * @ClassName MainActivity 
  20.  * @Description 循环滑动viewpager的一种方法,滑动很流畅。实现方法:在实际显示的界面头和尾分别增加一个界面。 
  21.  * @author Moto 
  22.  * @date 2014 2014-7-18 
  23.  *  
  24.  */  
  25. public class MainActivity extends Activity implements OnPageChangeListener {  
  26.   
  27.     private ViewPager mViewPager;  
  28.     private ViewGroup mPointViewGroup;  
  29.     private ArrayList<View> mViewPagerList;  
  30.     private boolean mIsChanged = false;  
  31.     private int mCurrentPagePosition = FIRST_ITEM_INDEX;  
  32.     private int mCurrentIndex;  
  33.     private static final int POINT_LENGTH = 3;  
  34.     private static final int FIRST_ITEM_INDEX = 1;  
  35.     private static final String TAG = "MOTO";  
  36.   
  37.     @Override  
  38.     protected void onCreate(Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setContentView(R.layout.activity_main);  
  41.         initUI();  
  42.     }  
  43.   
  44.     private void initUI() {  
  45.         mViewPager = (ViewPager) findViewById(R.id.viewpager);  
  46.         mPointViewGroup = (ViewGroup) findViewById(R.id.point_layout);  
  47.   
  48.         mViewPagerList = new ArrayList<View>();  
  49.         // 增加第1个界面,实际上他显示的是最后一个界面  
  50.         addTextView(POINT_LENGTH - 1);  
  51.         // 增加实际显示的2、3、4界面  
  52.         for (int i = 0; i < 3; i++) {  
  53.             addTextView(i);  
  54.             addPoint(i);  
  55.         }  
  56.         // 增加最后的第5个界面,实际上他显示的是第一个界面  
  57.         addTextView(0);  
  58.   
  59.         PagerAdapter pagerAdapter = new CustomPagerAdapter(mViewPagerList);  
  60.         mViewPager.setAdapter(pagerAdapter);  
  61.         mViewPager.setOnPageChangeListener(this);  
  62.         mViewPager.setCurrentItem(mCurrentPagePosition, false);  
  63.     }  
  64.   
  65.     private void addTextView(int pIndex) {  
  66.         TextView textview = new TextView(this);  
  67.         textview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));  
  68.         textview.setGravity(Gravity.CENTER);  
  69.         textview.setText("这是第" + (pIndex + 1) + "个页面");  
  70.         textview.setTextSize(50);  
  71.         mViewPagerList.add(textview);  
  72.     }  
  73.   
  74.     private void addPoint(int pIndex) {  
  75.         ImageView pointImageView = new ImageView(this);  
  76.         LayoutParams layoutParams = new LayoutParams(20, 20);  
  77.         layoutParams.setMargins(10, 0, 10, 0);  
  78.         pointImageView.setLayoutParams(layoutParams);  
  79.         pointImageView.setBackgroundResource(R.drawable.point_style);  
  80.         if (0 == pIndex) {  
  81.             pointImageView.setEnabled(false);  
  82.         }  
  83.         mPointViewGroup.addView(pointImageView);  
  84.     }  
  85.   
  86.     private void setCurrentDot(int positon) {  
  87.         // 界面实际显示的序号是第1, 2, 3。而点的序号应该是0, 1, 2.所以减1.  
  88.         positon = positon - 1;  
  89.         if (positon < 0 || positon > mViewPagerList.size() - 1 || mCurrentIndex == positon) {  
  90.             return;  
  91.         }  
  92.         mPointViewGroup.getChildAt(positon).setEnabled(false);  
  93.         mPointViewGroup.getChildAt(mCurrentIndex).setEnabled(true);  
  94.         mCurrentIndex = positon;  
  95.     }  
  96.   
  97.     @Override  
  98.     public void onPageScrollStateChanged(int pState) {  
  99.         if (ViewPager.SCROLL_STATE_IDLE == pState) {  
  100.             if (mIsChanged) {  
  101.                 mIsChanged = false;  
  102.                 mViewPager.setCurrentItem(mCurrentPagePosition, false);  
  103.             }  
  104.         }  
  105.     }  
  106.   
  107.     @Override  
  108.     public void onPageScrolled(int arg0, float arg1, int arg2) {  
  109.   
  110.     }  
  111.   
  112.     @Override  
  113.     public void onPageSelected(int pPosition) {  
  114.         mIsChanged = true;  
  115.         if (pPosition > POINT_LENGTH) {  
  116.             mCurrentPagePosition = FIRST_ITEM_INDEX;  
  117.         } else if (pPosition < FIRST_ITEM_INDEX) {  
  118.             mCurrentPagePosition = POINT_LENGTH;  
  119.         } else {  
  120.             mCurrentPagePosition = pPosition;  
  121.         }  
  122.         Log.i(TAG,"当前的位置是"+mCurrentPagePosition);  
  123.         setCurrentDot(mCurrentPagePosition);  
  124.     }  
  125.   
  126. }  

 

源码下在地址:https://github.com/bird7310/Demos.git

 

总结

希望对大家有帮助,多提意见。近段时间项目很赶,很长时间没看书写博客了。赶项目赶得都麻木了,放松放松,偷偷懒,写写博客吧。

posted @ 2014-08-25 10:26  dongweiq  阅读(492)  评论(0编辑  收藏  举报