android无限轮播广告的简单实现

好久也没写过博客了,今天兴致大发突然想写一篇博客,哈哈哈哈.....

今天的博客是关于无限轮播的广告,无限轮播的广告在各个市场应用是相当常见的,可能平时我们自己做的东西中是没有无限播放的。只是单次播放完之后直接跳到了第一页,当用户想从最后一张向右滑动的时候,却发现滑不动了,这是种不太好的体验.....

废话不多说了,先上个动图看看


1.实现方式的原理

      其实就是在数据集中增加了两张图片,在首位置增加最后一个图片,在最后一个位置增加第一张图片,然后处理滑动边界的时候,通过滑动边界的一些处理做到了伪无限循环。比如你从倒数第二张图片向滑动的时候,此时右边显示的图片是第一张图片,待你滑动完成时,也就是最后一张图片完全显示出来的时候,viewpager的位置立即切换到第二项,现在这时候显示出来的是第一张图片,指示器的位置也切换到第一个位置。这样就重新进行下一轮的循环啦。从第一张图片往左划的原理也是一样的。接下来从代码上讲讲一些道理。


2.重写的viewpager中滑动边界处理的代码

OnPageChangeListener mOnPagerChangeListener = new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            if (null != getAdapter() && getAdapter().getCount() > 1) {
               int count = getAdapter().getCount();
                if (position == 1 && prePosition == count - 1) {
                   prePosition = position;
                    return;
                }else if (position == count - 2 && prePosition == 0) {
                    prePosition = position;
                    return;
                }
                callBackIndicatotPosition(toRealPosition(position));
                prePosition = position;
            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            PagerAdapter adapter = getAdapter();
            if (adapter != null && adapter.getCount() > 1) {
                if (state == ViewPager.SCROLL_STATE_IDLE) {
                    int count = adapter.getCount();
                    if (getCurrentItem() == 0) {
                        setCurrentItem(count - 2,false);
                    } else if (getCurrentItem() == count - 1) {
                        setCurrentItem(1,false);
                    }
                }
            }
        }
    };OnPageChangeListener mOnPagerChangeListener = new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            if (null != getAdapter() && getAdapter().getCount() > 1) {
               int count = getAdapter().getCount();
                if (position == 1 && prePosition == count - 1) {
                   prePosition = position;
                    return;
                }else if (position == count - 2 && prePosition == 0) {
                    prePosition = position;
                    return;
                }
                callBackIndicatotPosition(toRealPosition(position));
                prePosition = position;
            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            PagerAdapter adapter = getAdapter();
            if (adapter != null && adapter.getCount() > 1) {
                if (state == ViewPager.SCROLL_STATE_IDLE) {
                    int count = adapter.getCount();
                    if (getCurrentItem() == 0) {
                        setCurrentItem(count - 2,false);
                    } else if (getCurrentItem() == count - 1) {
                        setCurrentItem(1,false);
                    }
                }
            }
        }
    };

如代码所以,每次滑动页面调用pagerSelected的时候。当不是边界处理的时候,都要重新调用callBackIndicatotPosition(toRealPosition(position))这个方法,我们来看一下这个方法。
  /**
     * 用于回调指示器的位置
     * @param position
     */
    private void callBackIndicatotPosition(int position) {
        if (null != pageChangeListeners && position >= 0) {
            for (OnPageChangeListener temp : pageChangeListeners) {
                temp.onPageSelected(position);
            }
        }
    };


   /**
     * 计算出指示器正确的显示位置
     */
    private int toRealPosition(int position) {
        if (getAdapter() != null && getAdapter().getCount() > 1) {
            int count = getAdapter().getCount();
            if (position == count - 1) {
               return 0;
            }else if (position == 0) {
                return count - 3;
            }else{
                return position - 1;
            }
        }
        return 0;
    }
其实这个方法就是用来回调指示器位置的,外部需要设置一个pagerListener,每次滑动页面完成的时候,都会回调外面的pagerselected方法来让指示器显示在正确的位置。当边界处理的时候,这里就不需要了。比如从倒数第二张广告图(实际上显示的是最后一张广告图)向右滑动最后一张图片(实际显示的是第一张图片)。这时候通过callBackIndicatotPosition方法指示器位置回回到0的位置。与此同时我们看看onPageScrollStateChanged方法,当然getCurrentItem() == count - 1的时候,我们直接调用setCurrentItem(1,false)这个方法,图片重新回到了第1的位置,也就是显示第一张广告图片的位置(第0的位置显示最后一张广告图),指示器也是0的位置,此时刚好全部回到初始位置了。
    同时,我们看看selected中的边界处理方法,当从显示最后一个位置的图片到直接显示第1位置的图片的时候,这时候指示器的位置就不需要重新设置了。因为从倒数第二个位置滑动到倒数第一个位置的时候,指示器的位置已经重新回0了。对应的代码就是
if (position == 1 && prePosition == count - 1) {
                   prePosition = position;
                    return;
                }
同样,当从图片1的位置向左滑显示图片0的时候,我们也是要做一下相应的边界处理。


3.注意的点
    关于注意的点也不多,其实就是在写Adapter的时候,重写getCount方法的时候,我们需要真实的图片数量加2。然后在instantiateItem中给0位置和最后一个位置分别设置最后一张图片和第一张图片。

  public int getCount() {
        int count = mImageViews.size();
        if (mImageViews.size() > 1) {
            return count + 2;
        } else {
            return count;
        }
    }


    public Object instantiateItem(ViewGroup container, int position) {
        int realPosition = position;
        int count = mImageViews.size();
        if (count > 0) {
            if (position == 0) {
                realPosition = count - 1;
            }else if (position == getCount() - 1) {
                realPosition = 0;
            } else {
                realPosition = position - 1;
            }
        }
        int Drawable = mImageViews.get(realPosition);

        if (null == mViews.get(position)) {
            onCreatView(position,Drawable);
        }
        ImageView view = mViews.get(position);
        view.setImageResource(Drawable);
        container.removeView(view);
        container.addView(view);
        return view;
    }

最后设置轮播的定时轮播的那些就比较简单,就不做介绍了。大家都会的了,用Handler设置就行了。项目里是封装了一个将各个事件处理都封装在一个LooperPagerView里面,外面设置调用然后设置相应的数据就可以了,指示器也可以根据需要自己去自定义一个相应的view来显示。

今天就写到这里,随便写了一点,当做记录一下吧....
项目地址:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值