• 自定义循环滑动的viewpager


    今天和大家分享一下如何定制一个可以循环滑动的viewpager。其实今天更重要的提供一种组件化思想,当然你可以理解为面向对象思想。

    吐槽一下网上流行的实现方式吧(为了方便说明,下文称之为方式A),方式A是重写adapter的getCount方法,返回一个很大的数(值为max),adapter中的getView方法中的position重新根据实际数量取模,把viewpager设置在max二分之一的位置。因为这个值很大所以基本不可能滑动到position=0或者position=max的位置,不过确切来说这并不是无限循环,采用脚本之类的应该可以滑动到边界(没有试验过)。

    我们的需求

    快速把之前viewpager相关的代码改成无限循环。

    这个需求很简单就是在已有的代码上完成无限循环。当然你可以根据方式A来完成,它是通过适配器来完成无限循环的,不过这种方式你需要改的代码并不少,毕竟你得改适配器。

    本文需要提供的方式B就登场了,好处在于不用改你的adapter,只需要把你的viewpager改成本文中的组件CycleViewPager就可以了,其他的都不用改。

    原理

    CycleViewPager继承ViewPager。当向右翻页(文中指的向右翻页是指手指由右向左滑,向左翻页反之),数据滑动到最后一条数据时调用setCurrentItem(0)返回第一条,当向左翻页,数据滑动到第一条数据时setCurrentItem(getCount()-1)返回到最后一条数据。在设置数据的时候需要多生成两条数据,比如原始数据是[a,b,c,d,e],那么生成的数据为[e,a,b,c,d,e,a],原始数据第一条前面加了最后一条数据e,原始数据的最后一条的后面加了原始数据的第一条数据a。从a滑到e时,继续向右翻页那么就到了数据a(最右边的那个a),停止滑动时调用setCurrentItem(1)返回第一条数据a(最左边的那个a);从e滑动到a时,继续向左翻页那么就到了数据e(做左边的那个e),停止滑动时调用setCurrentItem(5)。

    直接上代码

      1 package com.vane.widget.cycleviewpager;
      2 
      3 import android.content.Context;
      4 import android.database.DataSetObserver;
      5 import android.support.v4.view.PagerAdapter;
      6 import android.support.v4.view.ViewPager;
      7 import android.util.AttributeSet;
      8 import android.view.View;
      9 import android.view.ViewGroup;
     10 
     11 public class CycleViewPager extends ViewPager {
     12 
     13     private InnerPagerAdapter mAdapter;
     14 
     15     public CycleViewPager(Context context) {
     16         super( context);
     17         setOnPageChangeListener( null);
     18     }
     19 
     20     public CycleViewPager(Context context, AttributeSet attrs) {
     21         super( context, attrs);
     22         setOnPageChangeListener( null);
     23     }
     24 
     25     @Override
     26     public void setAdapter(PagerAdapter arg0) {
     27         mAdapter = new InnerPagerAdapter( arg0);
     28         super.setAdapter( mAdapter);
     29         setCurrentItem( 1);
     30     }
     31 
     32     @Override
     33     public void setOnPageChangeListener(OnPageChangeListener listener) {
     34         super.setOnPageChangeListener( new InnerOnPageChangeListener( listener));
     35     }
     36 
     37     private class InnerOnPageChangeListener implements OnPageChangeListener {
     38 
     39         private OnPageChangeListener listener;
     40         private int position;
     41 
     42         public InnerOnPageChangeListener(OnPageChangeListener listener) {
     43             this.listener = listener;
     44         }
     45 
     46         @Override
     47         public void onPageScrollStateChanged(int arg0) {
     48             if(null != listener) {
     49                 listener.onPageScrollStateChanged( arg0);
     50             }
     51             if(arg0 == ViewPager.SCROLL_STATE_IDLE) {
     52                 if(position == mAdapter.getCount() - 1) {
     53                     setCurrentItem( 1, false);
     54                 }
     55                 else if(position == 0) {
     56                     setCurrentItem( mAdapter.getCount() - 2, false);
     57                 }
     58             }
     59         }
     60 
     61         @Override
     62         public void onPageScrolled(int arg0, float arg1, int arg2) {
     63             if(null != listener) {
     64                 listener.onPageScrolled( arg0, arg1, arg2);
     65             }
     66         }
     67 
     68         @Override
     69         public void onPageSelected(int arg0) {
     70             position = arg0;
     71             if(null != listener) {
     72                 listener.onPageSelected( arg0);
     73             }
     74         }
     75     }
     76 
     77     private class InnerPagerAdapter extends PagerAdapter {
     78 
     79         private PagerAdapter adapter;
     80 
     81         public InnerPagerAdapter(PagerAdapter adapter) {
     82             this.adapter = adapter;
     83             adapter.registerDataSetObserver( new DataSetObserver() {
     84 
     85                 @Override
     86                 public void onChanged() {
     87                     notifyDataSetChanged();
     88                 }
     89 
     90                 @Override
     91                 public void onInvalidated() {
     92                     notifyDataSetChanged();
     93                 }
     94 
     95             });
     96         }
     97 
     98         @Override
     99         public int getCount() {
    100             return adapter.getCount() + 2;
    101         }
    102 
    103         @Override
    104         public boolean isViewFromObject(View arg0, Object arg1) {
    105             return adapter.isViewFromObject( arg0, arg1);
    106         }
    107 
    108         @Override
    109         public Object instantiateItem(ViewGroup container, int position) {
    110             if(position == 0) {
    111                 position = adapter.getCount() - 1;
    112             }
    113             else if(position == adapter.getCount() + 1) {
    114                 position = 0;
    115             }
    116             else {
    117                 position -= 1;
    118             }
    119             return adapter.instantiateItem( container, position);
    120         }
    121 
    122         @Override
    123         public void destroyItem(ViewGroup container, int position, Object object) {
    124             adapter.destroyItem( container, position, object);
    125         }
    126 
    127     }
    128 }

    如何使用

    使用方法和viewPager是一样一样的,你就认为是viewpager来使用就可以了。源码你可以在github上取https://github.com/vanezkw/cycleviewpager.git

    总结

    源码中大家也都看到了没有什么特别的其实就是平时讲的设计模式。之前提到的方式A个人认为并不完全是面向对象的方式,这个当然也看大家如何理解。

  • 相关阅读:
    二十几岁的事情之一,缩小理想!
    mysql数据库建表分类字段--尽量少用字符串--原因探索
    Linux 提升逼格之 命令别名 分享
    git 认证问题之一的解决 : http ssh 互换
    rabbitmqctl 命令整理
    golang 用defer 捕获error 需小心
    Linux 常用命令 随口说
    随便记录几个点
    喜鹊开发者(The Magpie Developer)
    主流开放平台接口说明
  • 原文地址:https://www.cnblogs.com/huolongluo/p/5538588.html
Copyright © 2020-2023  润新知