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。