android ViewPager实现的左右滑动广告框
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)
2)PagerAdapter只缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁
destroyItem(ViewGroup ,int , Object)
3)获取要滑动的控件的数量,在这里我们以滑动的广告栏为例,那么这里就应该是展示的广告图片的ImageView数量这里设置。
要想实现能滑到边缘图片还能滑动就需要在这里设置值了
getCount()
4) 来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可,官方就是这么写的,具体作用还不明确
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 }
运行的效果:
源码下载地址:源码