ViewPager:真正实现图片的无限轮播、自定义指示点和条目点击事件(支持长按暂停滚动)

概述


轮播组件在我们的APP中是很常见的,网上也能找到很多类似的Demo。这里把ViewPager进行了一些封装,支持开发者自定义条目布局,指示点样式,图片加载方式等,耦合低,方便使用。源码:https://github.com/jijinchao2014/CyclePager

对于轮播的原理大概就两种方式:

       1.使用Integer的最大值,直接让ViewPager从中间开始轮播,这样可以实现无限轮播,但不是真正意义的无限轮播;

       2.使用图片的size+2处理,在原始图片集合的首尾各加1,当ViewPager切换的时候自动进行position修正,这种方式是真正意义的无限轮播。

第一种方式比较简单,这篇小文章主要讲讲第二种的实现思路,这里我自定义了一个CyclePager,继承于ViewPager。


功能


我们先来看看这个自定义ViewPager有哪些功能吧:

  • 支持无限轮播;
  • 可定制指示点;
  • 可定制item的布局;
  • 可自定义ViewPager切换效果;
  • 支持item点击;
  • 按住停止轮播;
  • 抬手继续的功能



效果演示


截得图片比较卡顿,实际效果很流畅滴



实现


该实现主要在自定义的CyclePager中,里面进行了简单的封装,本身内部实现了adapter的修正,以及ViewPager切换的修正

代码通过内部重写的setAdapter()和addOnPageChangeListener()将修正adapter和listener进行引用(具体查看代码实现)


   adapter修正

        相比使用Integer的最大值,这里使用的是图片的size+2的方式实现了真正的无限轮播,如图:

   

         这样,当ViewPager切换D的时候,通过矫正adapter里的position使之后的变成A,当ViewPager在A的时候,使前一个变为D,由于集合长度发生变化,除了以上两种情况,其他的position的位置需要前移一个位置进行修正。

   /**
     * 修正adapter
     */
    public class InnerPagerAdapter extends PagerAdapter {

        private PagerAdapter adapter;

        public InnerPagerAdapter(PagerAdapter adapter) {
            this.adapter = adapter;
        }

        @Override
        public int getCount() {
            return adapter.getCount() + 2;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            if (position == getCount() - 1) {
                position = 0;
            } else if (position == 0) {
                position = adapter.getCount() - 1;
            } else {
                position -= 1;
            }
            return adapter.instantiateItem(container, position);
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            adapter.destroyItem(container, position, object);
        }
    }

   listener切换修正

            另外,也需要在viewpager切换的时候让静默地切换到修正页面

    /**
     * 修正listener
     */
    public class InnerPageChangeListener implements OnPageChangeListener {

        private OnPageChangeListener listener;
        private int position;

        public InnerPageChangeListener(OnPageChangeListener listener) {

            this.listener = listener;
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (listener != null) {
                listener.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }

        }

        @Override
        public void onPageSelected(int position) {
            this.position = position;
            if (listener != null) {
                listener.onPageSelected(position);
            }
            ......
        }

        @Override
        public void onPageScrollStateChanged(int state) {
    
             if (position == getAdapter().getCount() - 1) {
                CyclePager.this.setCurrentItem(1, false);
              } else if (position == 0) {
                CyclePager.this.setCurrentItem(getAdapter().getCount() - 2, false);
             }
            
            if (listener != null) {
                listener.onPageScrollStateChanged(state);
            }
        }
    }

使用


当然,这里给大家封装好了,直接使用即可,使用方法如下:

       1.在项目的build.gradle中添加依赖(或者把代码下载后将关键代码复制到自己的项目中):

 compile 'com.jijc.cyclepager:cyclepagerlibrary:2.0.2'

       2.布局文件中使用CyclePager

<com.jijc.cyclepagerlibrary.view.CyclePager
 android:id="@+id/viewpager"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"/>

       注意:如果需要添加指示点,则需要使用LinearLayout进行占位,开发者可自定义指示点的形状和显示的位置 只需要自己调整好布局即可(完整布局如下)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="135dp"
    tools:context="com.jijc.cyclepager.MainActivity">
    <com.jijc.cyclepagerlibrary.view.CyclePager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <LinearLayout
        android:visibility="gone"
        android:id="@+id/ll_point"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:gravity="center_vertical|right"
        android:padding="10dp"
        android:layout_alignParentBottom="true"
        android:layout_height="wrap_content">
    </LinearLayout>
</RelativeLayout>

         3.Activity或者Frgment中初始化CyclePager并按照需求进行一些必要设置

  • 设置指示点,如不需要可不调用

    viewpager.addPoints(mContext, R.drawable.bg_pointer1, ll_point, ListUtils.getSize(imgList));
  • CyclePager设置数据,详情参考方法注释

    viewpager.setImages(mContext, imgList, R.layout.item_cycle_pager, new CyclePager.OnItemInitLisenter() {
            @Override
            public void initItemView(View view, int position) {
    
                ImageView iv_img = (ImageView) view.findViewById(R.id.iv_img);
                TextView tv_play_count = (TextView) view.findViewById(R.id.tv_play_count);
                tv_play_count.setText("这是第" + (position + 1) + "个图片");
                Object tag = iv_img.getTag();
                if (tag == null || !TextUtils.equals((String) tag, imgList.get(position))) {
                    ImageLoader.loadImageAsync(iv_img, imgList.get(position), DisplayImageOptionsCfg.getInstance().getOptions(R.mipmap.item_live_bg));
                    iv_img.setTag(imgList.get(position));
                }
            }
    
            @Override
            public void onItemClick(int position) {
                Toast.makeText(mContext, "pos:" + (position + 1) + "-url:" + imgList.get(position), Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onItemVisible(int position) {
    
            }
        }, 6);  
  • 设置切换效果,如果想使用默认效果则不必设置

    viewpager.setPageTransformer(new DepthPageTransformer());
  • 开启自动轮播并设置轮播间隔,如不需要可不调用

    viewpager.startRoll(3000);

        4.如果启动了自动滚动,开发者想要在某种情况(比如退出页面)停止滚动时可使用如下方法:

viewpager.stopRoll();

好了,到这里一个可以无限轮播的ViewPager就完成了,大家可直接通过as添加依赖进行引用,eclipse可下载代码进行copy,多的不说了,还有更优的方式,望大家多提宝贵意见!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值