ViewPager
1.先对ViewPager这个控件进行一些了解,
PagerAdapter是 android.support.v4包中的类,它的子类有FragmentPagerAdapter, FragmentStatePagerAdapter,这两个adapter都是Fragment的适配器,用于实现Fragment的滑动效果。PagerAdapter主要是viewpager的适配器,而viewPager则也是在 android.support.v4扩展包中新添加的一个强大的控件,可以实现控件的滑动效果,比如咱们在软件中常见的广告栏的滑动效果,用viewPager就可以实现。今天主要介绍如何使用viewPagr并重写PagerAdapter实现常见广告栏的滑动效果
但GOOLE官方更希望将ViewPager与Fragment相结合起来一起使用的。
2.ViewPager要用到的适配器是PagerAdapter,这里PAI的解释:
在使用ViewPager常用设置
1)ViewPager.setOffscreenPageLimit(2);//设置缓存view 的个数(实际有3个,缓存2个+正在显示的1个)
2)ViewPager.setPageMargin((int)getResources().getDimensionPixelOffset(R.dimen.ui_5_dip));//
设置viewpager每个页卡的间距,与gallery的spacing属性类似
3)ViewPager更新数据问题:
直接使用notifyDataSetChanged是无法更新,需要同时重写getItemPosition返回常量 POSITION_NONE (此常量为viewpager带的)。
在继承了PagerAdapter后主要复写那个4个方法。
1)当要显示的图片可以进行缓存的时候,会调用这个方法进行显示图片的初始化,我们将要显示的ImageView加入到ViewGroup中,然后作为返回值返回即可,
而PagerAdapter缓存的图片是三张 (后面给出证明)
instantiateItem(ViewGroup, int)
PagerAdapter只缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁
destroyItem(ViewGroup ,int , Object)
获取要滑动的控件的数量,在这里我们以滑动的广告栏为例,那么这里就应该是展示的广告图片的ImageView数量这里设置。
要想实现能滑到边缘图片还能滑动就需要在这里设置值了
getCount()
来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可,官方就是这么写的,具体作用还不明确
isViewFromObject(View, Object)
3.再是用PagerAdapter的时候经常会遇到这个:The specified child already has a parent. You must call removeView
解决方法和思路可以参考这个地址:解决办法
主要的意思就是:子view在引用的时候必须和父view一起被引用,不能脱离父view而被单独引用,除非子view和父view之间脱离了关系就可以了
4.通过一个小例子来进一步解释PagerAdapter:
activity的xml文件:
1 <LinearLayout 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 android:orientation="horizontal"
6 tools:context=".MainActivity" >
7
8 <android.support.v4.view.ViewPager
9 android:id="@+id/viewPager"
10 android:layout_width="fill_parent"
11 android:layout_height="wrap_content" />
12
13 </LinearLayout>
MainActivity:
1 public class MainActivity extends Activity {
2 int i = 0;
3 int j = 0;
4 private ViewPager viewPager;
5
6 private int[] imageID;
7
8 private ImageView[] imageViews;
9
10 @Override
11 protected void onCreate(Bundle savedInstanceState) {
12 super.onCreate(savedInstanceState);
13 setContentView(R.layout.activity_main);
14 viewPager = (ViewPager) findViewById(R.id.viewPager);
15 imageID = new int[] { R.drawable.p1, R.drawable.p2, R.drawable.p3,
16 R.drawable.p4, R.drawable.p5, R.drawable.p6 };
17 imageViews = new ImageView[imageID.length];
18 for (int i = 0; i < imageViews.length; i++) {
19 ImageView imageView = new ImageView(this);
20 imageView.setBackgroundResource(imageID[i]);
21 imageViews[i] = imageView;
22 }
23
24 viewPager.setAdapter(new myAdapter());
25
26 }
27
28 class myAdapter extends PagerAdapter {
29
30 @Override
31 public int getCount() {
32 return imageViews.length;
33 }
34
35 @Override
36 public boolean isViewFromObject(View arg0, Object arg1) {
37 return arg0 == arg1;
38 }
39
40 @Override
41 public Object instantiateItem(ViewGroup container, int position) {
42 System.out.println("instantiateItem执行了" + (++i) + "次 ,执行位置--->>"
43 + position);
44 container.addView(imageViews[position], 0); // 将ImageView装到pagerView当中去
45 return imageViews[position];
46 }
47
48 @Override
49 public void destroyItem(ViewGroup container, int position, Object object) {
50 System.out.println("destroyItem执行了" + (++i) + "次 ,执行位置--->>"
51 + position);
52 container.removeView(imageViews[position]);
53 }
54
55 }
56
57 }
运行后的效果:
在程序运行成功后,打印出了:
这张图片说明ViewPager初始化的时候,是加载了两张图片进去的
在滚动两张图片后打印出:
滚动后instantiateItem是先执行了三次,因为PagerAdapter的缓存熟默认是3,可以修改缓存熟在试试,在滚动后图片数量超过三张后,就会三处最边缘的一张。
虽然实现了图片滚动,但没有达到广告的那种效果。下面进一步的改进
注意:若只有三张图片参与滚动下面方法就会报错,请参考上面的连接。
activity的xml文件:
1 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 android:layout_width="fill_parent"
3 android:layout_height="fill_parent"
4 android:orientation="vertical" >
5
6 <android.support.v4.view.ViewPager
7 android:id="@+id/viewPager"
8 android:layout_width="fill_parent"
9 android:layout_height="wrap_content" />
10
11 <RelativeLayout
12 android:layout_width="fill_parent"
13 android:layout_height="wrap_content"
14 android:orientation="vertical" >
15
16 <LinearLayout
17 android:id="@+id/viewGroup"
18 android:layout_width="fill_parent"
19 android:layout_height="wrap_content"
20 android:layout_alignParentBottom="true"
21 android:layout_marginBottom="30dp"
22 android:gravity="center_horizontal"
23 android:orientation="horizontal" >
24 </LinearLayout>
25 </RelativeLayout>
26
27 </FrameLayout>
MianActivity:
1 public class MainActivity extends Activity implements OnPageChangeListener {
2 private ViewPager viewPager;
3
4 private int[] imageID;
5
6 private ImageView[] imageViews;
7
8 private ImageView[] tips;
9
10 @Override
11 protected void onCreate(Bundle savedInstanceState) {
12 super.onCreate(savedInstanceState);
13 setContentView(R.layout.activity_main);
14 viewPager = (ViewPager) findViewById(R.id.viewPager);
15 imageID = new int[] { R.drawable.p1, R.drawable.p2, R.drawable.p3,
16 R.drawable.p4, R.drawable.p5, R.drawable.p6 };
17 imageViews = new ImageView[imageID.length];
18 for (int i = 0; i < imageViews.length; i++) {
19 ImageView imageView = new ImageView(this);
20 imageView.setBackgroundResource(imageID[i]);
21 imageViews[i] = imageView;
22 }
23 ViewGroup viewGroup = (ViewGroup) findViewById(R.id.viewGroup);
24 tips = new ImageView[imageViews.length];
25 // 装小圆点
26 for (int j = 0; j < imageViews.length; j++) {
27 ImageView img = new ImageView(this);
28 img.setLayoutParams(new LayoutParams(20, 20));
29 tips[j] = img;
30 if (j == 0) {
31 tips[j].setBackgroundResource(R.drawable.page_indicator_focused);
32 } else {
33 tips[j].setBackgroundResource(R.drawable.page_indicator_unfocused);
34 }
35 viewGroup.addView(img);
36 }
37
38 viewPager.setAdapter(new myAdapter());
39 viewPager.setOnPageChangeListener(this);
40 viewPager.setCurrentItem(imageViews.length * 100);// 这样设置初始化的图片就是显示Integer.MAX_VALUE图片中第imageViews.length
41 // * 100张,这样就可以往左右翻了
42 }
43
44 class myAdapter extends PagerAdapter {
45
46 @Override
47 public int getCount() {
48 return Integer.MAX_VALUE;
49 }
50
51 @Override
52 public boolean isViewFromObject(View arg0, Object arg1) {
53 return arg0 == arg1;
54 }
55
56 @Override
57 public Object instantiateItem(ViewGroup container, int position) {
58 // System.out.println("instantiateItem执行了" + (++i) + "次 ,执行位置--->>"
59 // + position);
60 container.addView(imageViews[position % imageViews.length], 0); // 取余数后,每次添加的都是之前的6张图片了
61 return imageViews[position % imageViews.length];
62 }
63
64 @Override
65 public void destroyItem(ViewGroup container, int position, Object object) {
66 // System.out.println("destroyItem执行了" + (++i) + "次 ,执行位置--->>"
67 // + position); 这里在打印出来,就会懂原理了
68 container.removeView(imageViews[position % imageViews.length]);
69 }
70
71 }
72
73 @Override
74 public void onPageScrollStateChanged(int arg0) {
75
76 }
77
78 @Override
79 public void onPageScrolled(int arg0, float arg1, int arg2) {
80
81 }
82
83 @Override
84 public void onPageSelected(int arg0) {
85 setImageBackground(arg0 % imageViews.length);
86 }
87
88 private void setImageBackground(int selectItems) {
89 for (int i = 0; i < tips.length; i++) {
90 if (i == selectItems) {
91 tips[i].setBackgroundResource(R.drawable.page_indicator_focused);
92 } else {
93 tips[i].setBackgroundResource(R.drawable.page_indicator_unfocused);
94 }
95 }
96 }
97 }
运行的效果:
源码下载地址:源码