Android中的ListView可以实现屏幕上下滑动来浏览数据,ViewPager则实现了左右滑动的效果。我们可以拿它做很多事情,从最简单的导航,到页面菜单等等。ViewPager类提供了多界面切换的新效果。新效果有如下特征:

[1] 当前显示一组界面中的其中一个界面。

[2] 当用户通过左右滑动界面时,当前的屏幕显示当前界面和下一个界面的一部分。

[3]滑动结束后,界面自动跳转到当前选择的界面中。

下面的代码实现了一个图片循环滚动的功能。首先是布局文件,使用了一个ViewPager控件:

1. <span style="padding: 0px; margin: 0px; font-size: 14px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
2. xmlns:tools="http://schemas.android.com/tools"  
3. android:layout_width="match_parent"  
4. android:layout_height="match_parent" >  
5.   
6. <android.support.v4.view.ViewPager  
7. android:id="@+id/viewpager"  
8. android:layout_width="match_parent"  
9. android:layout_height="match_parent" >  
10. </android.support.v4.view.ViewPager>  
11.   
12. <LinearLayout  
13. android:layout_width="fill_parent"  
14. android:layout_height="wrap_content"  
15. android:layout_alignBottom="@id/viewpager"  
16. android:background="#33000000"  
17. android:orientation="vertical"  
18. android:padding="5dip" >  
19.   
20. <TextView  
21. android:id="@+id/tv_image_description"  
22. android:layout_width="wrap_content"  
23. android:layout_height="wrap_content"  
24. android:layout_gravity="center_horizontal"  
25. android:text="第一个引导页面"  
26. android:textColor="@android:color/white"  
27. android:textSize="14sp" />  
28.   
29. <LinearLayout  
30. android:id="@+id/ll_points"  
31. android:layout_width="wrap_content"  
32. android:layout_height="wrap_content"  
33. android:layout_marginTop="5dip"  
34. android:layout_gravity="center_horizontal"  
35. android:orientation="horizontal" >  
36. </LinearLayout>  
37. </LinearLayout>  
38.   
39. </RelativeLayout></span>


ViewPager的适配器是PagerAdapter,它是基类提供适配器来填充页面ViewPager内部。


接下来实现一个继承PagerAdapter的MyAdapter类,实现一个PagerAdapter,必须至少覆盖以下方法:

    • instantiateItem(ViewGroup, int)
    • destroyItem(ViewGroup, int, Object)
    • getCount()
    • isViewFromObject(View, Object)

    1. <span style="padding: 0px; margin: 0px; font-size: 14px;">package com.example.viewpagertest;  
    2.   
    3. import java.util.List;  
    4.   
    5. import android.support.v4.view.PagerAdapter;  
    6. import android.view.View;  
    7. import android.view.ViewGroup;  
    8. import android.widget.ImageView;  
    9.   
    10. class ViewPagerAdapter extends PagerAdapter {  
    11. private List<ImageView> mImageViewList;  
    12. public ViewPagerAdapter(List<ImageView> imageViewList) {  
    13. super();  
    14. this.mImageViewList = imageViewList;  
    15.     }  
    16. /**
    17.      * 该方法将返回所包含的 Item总个数。为了实现一种循环滚动的效果,返回了基本整型的最大值,这样就会创建很多的Item,
    18.      * 其实这并非是真正的无限循环。
    19.      */  
    20. @Override  
    21. public int getCount() {  
    22. return Integer.MAX_VALUE;  
    23.     }  
    24. /**
    25.      * 判断出去的view是否等于进来的view 如果为true直接复用
    26.      */  
    27. @Override  
    28. public boolean isViewFromObject(View arg0, Object arg1) {  
    29. return arg0 == arg1;  
    30.     }  
    31. /**
    32.      * 销毁预加载以外的view对象, 会把需要销毁的对象的索引位置传进来,就是position,
    33.      * 因为mImageViewList只有五条数据,而position将会取到很大的值,
    34.      * 所以使用取余数的方法来获取每一条数据项。
    35.      */  
    36. @Override  
    37. public void destroyItem(ViewGroup container, int position, Object object) {  
    38.         container.removeView(mImageViewList.get(position % mImageViewList.size()));  
    39.     }  
    40. /**
    41.      * 创建一个view,
    42.      */  
    43. @Override  
    44. public Object instantiateItem(ViewGroup container, int position) {  
    45.         container.addView(mImageViewList.get(position % mImageViewList.size()));  
    46. return mImageViewList.get(position % mImageViewList.size());  
    47.     }  
    48. }  
    49. </span>


    最后是主界面部分的代码:

    1. <span style="padding: 0px; margin: 0px; font-size: 14px;">package com.example.viewpagertest;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. import android.app.Activity;  
    7. import android.os.Bundle;  
    8. import android.os.Handler;  
    9. import android.os.Message;  
    10. import android.os.SystemClock;  
    11. import android.support.v4.view.ViewPager;  
    12. import android.support.v4.view.ViewPager.OnPageChangeListener;  
    13. import android.view.View;  
    14. import android.widget.ImageView;  
    15. import android.widget.LinearLayout;  
    16. import android.widget.LinearLayout.LayoutParams;  
    17. import android.widget.TextView;  
    18.   
    19. public class MainActivity extends Activity implements OnPageChangeListener {  
    20.   
    21. private List<ImageView> imageViewList;  
    22. private TextView tvDescription;  
    23. private LinearLayout llPoints;  
    24. private String[] imageDescriptions;  
    25. private int previousSelectPosition = 0;  
    26. private ViewPager mViewPager;  
    27. private boolean isLoop = true;  
    28. private Handler handler = new Handler() {  
    29.   
    30. @Override  
    31. public void handleMessage(Message msg) {  
    32. super.handleMessage(msg);  
    33.   
    34. 1);  
    35.         }  
    36.     };  
    37.   
    38. @Override  
    39. protected void onCreate(Bundle savedInstanceState) {  
    40. super.onCreate(savedInstanceState);  
    41.         setView();  
    42.         initView();  
    43.     }  
    44.   
    45. public void setView() {  
    46.         setContentView(R.layout.activity_splash_viewpager);  
    47.   
    48. // 自动切换页面功能  
    49. new Thread(new Runnable() {  
    50.   
    51. @Override  
    52. public void run() {  
    53. while (isLoop) {  
    54. 2000);  
    55. 0);  
    56.                 }  
    57.             }  
    58.         }).start();  
    59.     }  
    60.   
    61. public void initView() {  
    62.         mViewPager = (ViewPager) findViewById(R.id.viewpager);  
    63.         tvDescription = (TextView) findViewById(R.id.tv_image_description);  
    64.         llPoints = (LinearLayout) findViewById(R.id.ll_points);  
    65.           
    66.         prepareData();  
    67.           
    68. new ViewPagerAdapter(imageViewList);  
    69.         mViewPager.setAdapter(adapter);  
    70. this);  
    71.           
    72.         tvDescription.setText(imageDescriptions[previousSelectPosition]);  
    73. true);  
    74.           
    75. /**
    76.          * 2147483647 / 2 = 1073741820 - 1 
    77.          * 设置ViewPager的当前项为一个比较大的数,以便一开始就可以左右循环滑动
    78.          */  
    79. //我加了这部分代码即可实现
    80. int n = Integer.MAX_VALUE / 2 % imageViewList.size();  
    81. int itemPosition = Integer.MAX_VALUE / 2 - n;  
    82.           
    83.         mViewPager.setCurrentItem(itemPosition);  
    84. //
    85.     }  
    86.       
    87. private void prepareData() {  
    88. new ArrayList<ImageView>();  
    89. int[] imageResIDs = getImageResIDs();  
    90.             imageDescriptions = getImageDescription();  
    91.               
    92.             ImageView iv;  
    93.             View view;  
    94. for (int i = 0; i < imageResIDs.length; i++) {  
    95. new ImageView(this);  
    96.                 iv.setBackgroundResource(imageResIDs[i]);  
    97.                 imageViewList.add(iv);  
    98.                   
    99. // 添加点view对象  
    100. new View(this);  
    101.                 view.setBackgroundDrawable(getResources().getDrawable(R.drawable.point_background));  
    102. new LayoutParams(5, 5);  
    103. 10;  
    104.                 view.setLayoutParams(lp);  
    105. false);  
    106.                 llPoints.addView(view);  
    107.             }  
    108.         }  
    109.           
    110. private int[] getImageResIDs() {  
    111. return new int[]{  
    112.                     R.drawable.bg1,  
    113.                     R.drawable.bg2,  
    114.                     R.drawable.bg3,  
    115.                     R.drawable.pic_01,  
    116.                     R.drawable.pic_02  
    117.             };  
    118.         }  
    119.           
    120. private String[] getImageDescription() {  
    121. return new String[]{  
    122. "第一个引导页面",  
    123. "第二个引导页面",  
    124. "第三个引导页面",  
    125. "第四个引导页面",  
    126. "第五个引导页面"  
    127.             };  
    128.         }  
    129.   
    130. @Override  
    131. public void onPageScrollStateChanged(int arg0) {  
    132.               
    133.         }  
    134.   
    135. @Override  
    136. public void onPageScrolled(int arg0, float arg1, int arg2) {  
    137.               
    138.         }  
    139.   
    140. @Override  
    141. public void onPageSelected(int position) {  
    142. // 改变图片的描述信息  
    143.             tvDescription.setText(imageDescriptions[position % imageViewList.size()]);  
    144. // 切换选中的点,把前一个点置为normal状态  
    145. false);  
    146. // 把当前选中的position对应的点置为enabled状态  
    147. true);  
    148.             previousSelectPosition = position  % imageViewList.size();  
    149.         }  
    150.   
    151. @Override  
    152. protected void onDestroy() {  
    153. super.onDestroy();  
    154. false;  
    155.     }  
    156.   
    157. }  
    158. </span>


    此处并不是一个真正的无限循环,只是把ViewPager要加载的数据项设置成了一个很大的数值,给人一种感觉是可以无限循环滚动的。这里实现的自动滑动,还有就是监听OnPageChangedListener,实现手动滑动,网上基本都是这种思路,在getCount()中返回一个较大的值,比如500,然后初始时设置mViewPager.currentItem(300或者其他),因为一般人不会划到那么多次。


    顺便提一下ViewFlipper和ViewFlow,

    1、ViewPager(android.support.v4.view.ViewPager)与ViewFlow都能够使用适配器(ViewPager--PagerAdapter;ViewFlow--BaseAdapter)进行大量数据的适配,并且ViewFlow也带有原点和标题的位置提示,二者比较相像;

    2、ViewFlipper使用时主要在有限的少数页面切换中比较合适,并且能够自定义每一个切换动画,用于一个应用间的画面切换比较合适,类似于ActvityGroup;

    3、ViewFlow由于提供源码,所以在扩展上更强,可根据需要自行定制,比如加入循环播放等;

    4、当需要再一系列不确定数据的View中滑动时,可以考虑使用ViewFlow;如果View数目确定,应该改用Fragments或者兼容库里的ViewPager。