一般情况下,我们定义的ViewPager在翻到最后一个页面后将不能够滑动,翻到第一个页面后也不能够滑动,但是我们却经常会看到很多手机APP会循环显示ViewPager的页面。
实现这种循环的方式有两种:一种是实现真正的循环;一种实现伪循环。下面我们分别看看两种循环不同实现方法。
我们一共显示的的有三张视图,但是为了循环显示,我们需要在添加到PagerAdapter的数据集合mViews中在增添两个,也就是下图中的0和4。也就是数据集合的长度要比我们显示视图的长度大2。当视图显示到第4时,让其跳转至1;当视图到达0时, 让其跳转至3,一次形成循环。这种循环的缺点就是从最后一张跳向第一张或从第一张跳向最后一张时,动作不自然。
1. 定义总体布局。
<LinearLayout 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" tools:context=".MainActivity">
<android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
2**. 定义三个页面的布局,这里不再列举,每个布局只包含有一张ImageView图片。定义MyPagerAdapter适配器继承PagerAdapter适配器。**
public class MyPagerAdapter extends PagerAdapter {
private List<View> mViews;//三个布局的集合
/* 通过构造器获得数据 */
public MyPagerAdapter(List<View> mViews) {
this.mViews = mViews;
}
@Override
public int getCount() {
return mViews.size();//显示的布局的数量,我们这里为三个。
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
//增加View
container.addView(mViews.get(position));
return mViews.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//删除View
container.removeView(mViews.get(position));
}
}
3. Activity中通过监听Viewpager对象的滑动来实现循环,原理在之前讲的很清楚。
public class MainActivity extends Activity {
private ViewPager mViewPager;//定义ViewPager的对象
private List<View> mViews;//定义布局的集合
private LayoutInflater mInflater;
private MyPagerAdapter mPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mInflater = getLayoutInflater();
mViews = new ArrayList<View>();
View view0 = mInflater.inflate(R.layout.item_frist,null);
View view1 =mInflater.inflate(R.layout.item_frist, null);
View view2 =mInflater.inflate(R.layout.item_second, null);
View view3 =mInflater.inflate(R.layout.item_third, null);
View view4 =mInflater.inflate(R.layout.item_third, null);
mViews.add(view0);
mViews.add(view1);
mViews.add(view2);
mViews.add(view3);
mViews.add(view4);
mPagerAdapter = new MyPagerAdapter( mViews);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(1);
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if ( mViews.size() > 1) { //多于1,才会循环跳转
if ( position < 1) { //首位之前,跳转到末尾(N)
mViewPager.setCurrentItem(3, false);
position = 3;
Log.d("data", ""+mViews.get(position));
} else if ( position > 3) { //末位之后,跳转到首位(1)
mViewPager.setCurrentItem(1, false); //false:不显示跳转过程的动画
position = 1;
Log.d("data", ""+mViews.get(position));
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
效果展示:
大家应该都知道在PagerAdapter中有一个方法getCount(),该方法返回的是ViewPager显示的页面的数量。我们可以实现给一种假的循环:通过将getCount()方法返回的页面数量设置一个最大值,这个值可以上达万数(在程序中我们使用Integer.MAX_VALUE这个值),然后这几万个页面我们重复添加我们要显示的页面,这样用户在滑动过程中就一直在重复的看,就像真的实现了一种循环。但实际上并不是一个循环,而是添加的页面比较多,并且这些页面重复显示,而用户又不会滑动屏幕上万次,所以就像在循环看那几个页面。我们通过图来表示一下。
大家可能会想,我们一下添加上万个页面会不会占用内存啊……答案是:并不会。通过getCount()方法返回的页面数量虽然很大。但是这些页面不会真正的生成在内存中,真正的页面就是mViews存储的页面,大小就是的size()。
1. 定义总体布局。
<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" tools:context=".MainActivity">
<android.support.v4.view.ViewPager android:id="@+id/viewpager_second" android:layout_width="match_parent" android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</RelativeLayout>
2**. 定义三个页面的布局,这里不再例句。定义MyPagerAdapter适配器继承PagerAdapter适配器。这里有改变,getCount()方法返回值为Integer.MAX_VALUE, 在**
public class MyPagerAdapter extends PagerAdapter {
private List<View> mViews;
public MyPagerAdapter(List<View> mViews) {
this.mViews = mViews;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;//此处设置为最大值。
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = mViews.get(position%mViews.size());//通过取模获得在mViews中存储的页面
if(view.getParent()!=null){
container.removeView(view);//如果页面在之前存在,先将其删除后在添加
}
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
}
3. Activity中通过监听Viewpager对象的滑动来实现循环,原理在之前讲的很清楚。
public class MainActivity extends Activity {
private ViewPager mViewpagerSecond;
private List<View> mViews;
private LayoutInflater mInflater;
private MyPagerAdapter myPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewpagerSecond = (ViewPager) findViewById(R.id.viewpager_second);
mInflater = getLayoutInflater();
//初始化页面
mViews = new ArrayList<View>();
View view1 = mInflater.inflate(R.layout.viewpager_item_one, null);
View view2 = mInflater.inflate(R.layout.viewpager_item_two, null);
View view3 = mInflater.inflate(R.layout.viewpager_item_three, null);
mViews.add(view1);
mViews.add(view2);
mViews.add(view3);
myPagerAdapter = new MyPagerAdapter(mViews);
mViewpagerSecond.setAdapter(myPagerAdapter);
//设置启动时显示的界面。
mViewpagerSecond.setCurrentItem(Integer.MAX_VALUE/2-Integer.MAX_VALUE/2%mViews.size());
}