您的位置:首页 > 移动开发 > Android开发

Android玩转ViewPager(一) 实现循环滚动

2018-03-24 18:06 183 查看
循环滚动应用场景还是较多的,这里是支付宝一个例子



两个ImageVIew并提供了自动轮播以及手动无限翻页的功能。

先总结一下VIewPager的基础。

ViewPager是什么



继承了ViewGroup所以本身用于存放View,而自动翻页的特效无非就是自身Canvas的移动,通过Scroll来实现。

PagerAdapter是什么

PagerAdapter称ViewPager的适配器,为什么叫适配器呢,一种设计模式其实就是提供了相关的View给ViewPager,在ViewPager展示很多内容情况下如果将所有的View都添加到ViewPager上,则给内存带来了不必要的开销,所以ViewPager有个缓存机制,每次从PagerAdapter拿取设定数量的View,随着用户滑动而不断地销毁本身已展示过的View并从PagerAdapter拿取新的View。而PagerAdapter本身为抽象类,所以详见它的具体实现类。

PagerAdapter的具体实现类

myPagerAdapter extends PagerAdapter

我们自定义一个类直接继承它并实现抽象方法

public class myPagerAdapter extends PagerAdapter {

@Override
public int getCount() {
return 0;  //告诉ViewPager有多少View需要展示
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;   //确定一个页面视图是否关联到一个特定的对象,一般返回这个判断
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
//这里的container则是ViewPager本身,position是当前需要展示View的位置
{......我们的代码}
//在这里我们将View添加到ViewPager
//所以当ViewPager需要新的View的情况下就会调用这个方法
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
{....我们的代码}
//于此相对销毁展示过的View调用这个方法, position为需要销毁View的位置
}
}


FragmentPagerAdapter

官方实现的一个可以添加Fragment的ViewPager适配器,当然我们也需要再次继承它来放入Fragment。

public class myFragementAdapter extends FragmentPagerAdapter {

public myFragementAdapter(FragmentManager fm) {
super(fm);
//操作Fragment必然需要一个FragmentManager
}

@Override
public Fragment getItem(int position) {
{.....我们的代码}
//同上ViewPager需要的Fragment从这里获取,position为需要展示的位置
}

@Override
public int getCount() {
return 0;  //需要展示Fragment的数量
}

}


可以看到使用这个适配器我们的代码量是很少的,只需要提供相对应的Fragment即可,而具体的添加移除细节我们则不用考虑。



具体加载方法适配器本身已经做到了

FragmentStatePagerAdapter

public class myFragementAdapter extends FragmentStatePagerAdapter {

public myFragementAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {

}

@Override
public int getCount() {
return 0;
}

}


方法竟与FragmentPagerAdapter完全一样? 没错FragmentPagerAdapter与FragmentStatePagerAdapter都是实现了ViewPager加载Fragment,只是加载的机制不同,前者在内部会有一个缓存机制,也就是说不同的Fragment只调用一次getItem(int position)方法,当前页面超过了ViewPager本身的加载数量后不对其进行销毁,具体可自行百度Fragment的生命周期。所以用这个适配器时可在Fragment内部缓存View即缓存我们对View的操作,所以一般常用app的主界面。而后者体现在销毁上,当偏离了ViewPager加载的数量后对其Fragment进行销毁,所以再次需要Fragment时又要重新调用getItem(int position)方法,因此用这个适配器在Fragment内部不能缓存View,所以常用展示量较大的场景。

ViewPager.PageTransformer

该接口主要规定了ViewPager在切换View这个过程中多次调用的方法,其实就是动画的实现方法

public class fadeInFadeOut implements ViewPager
4000
.PageTransformer {

@Override
public void transformPage(View page, float position) {
if(position<1&&position>0){
page.setAlpha(1-position);
}
else if(position>-1&&position<0){
page.setAlpha(1+position);
}
}
}


这是笔者演示定义的一个简单例子,这个方法提供了两个参数(page:VIewPager指定加载(缓存)几个View后,这些View都会被分别传入进来,position:这个position不同于适配器的position,这个是根据View的顺序以及在屏幕中展示的位置来确定的)



笔者方便说明画了个图,这个ViewPager宽度刚好被两个View所填充,那么此时View1的postion为-1,view2为-0.5,view3为0,view4为0.5,也就是说当一个View刚好碰到ViewPager的left时候值为0,碰到right时候值为1,在其内部则为0-1,假定ViewPager缓存的VIew为无穷大,那么最左边的postion为负无穷大,右边为正无穷大。所以我们可以根据滑动过程传入的值来自定义我们想要的动画了。

ViewPager的循环滑动

实现循环滑动则需要做到将相同的View在不同的position展示出来即可,所以我们用到FragmentStatePagerAdapter

实现FragmentStatePagerAdapter

public class myFragementAdapter extends FragmentStatePagerAdapter {

List<Fragment> list;      //方便起见我们直接创建一个List,List其实对于PagetAdapter是没有意义的

public myFragementAdapter(FragmentManager fm, List<Fragment> li) {
super(fm);
list = li;    //在构造函数中传入包含一定数量的Fragment的List
}

@Override
public Fragment getItem(int position) {
return list.get(position % list.size());   //当读取到集合最后一位时又从第一位开始读取。
}

@Override
public int getCount() {
return Integer.MAX_VALUE;
}

}


配置VIewPager

public class MainActivity extends AppCompatActivity {

ViewPager viewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
viewPager = (ViewPager) findViewById(R.id.packager);   //找到ViewPager对象

int[] ints = {R.mipmap.one, R.mipmap.two, R.mipmap.there, R.mipmap.four};     //定义一个图片资源地址数组用于产生不同的IamgeView

List<android.support.v4.app.Fragment> list = ImageViewUtil.getFragmentList(this, ints);   //笔者定义的一个工具类,主要就是传入资源数组生成一个包裹Fragment的List
myFragementAdapter myPagerAdapter = new myFragementAdapter(getSupportFragmentManager(), list);

viewPager.setOffscreenPageLimit(1);   //设置ViewPager的加载(缓存)数量,默认为1,指的同时加载超出ViewPager外的View左右两端数量各为1.

viewPager.setAdapter(myPagerAdapter);

viewPager.setPageTransformer(true, new fadeInFadeOut());   //自定义的翻页动画
}
}


看下效果图



是不是可以多次看到这个小美女相同的照片了。 ok,手动循环滚动就搞定了,自动的无非就是多加行代码而已,

handler.postDelayed(new Runnable() {
@Override
public void run() {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
handler.postDelayed(this, 2000);
}
}, 2000);


viewPager.setCurrentItem()

这个方法用于设定ViewPager的显示位置,虽说有动画效果不过速度较快,需要修改速度就要用到反射改变ViewPager内部的Scroller,具体自行百度。

ViewPager+Fragment的懒加载见下篇。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息