Android 轮播Banner 实现 附代码

今天面试头条,有个面试官问我,怎么实现Banner 轮播?

我当时解答就是,记录一个count,每次滑动一次,把count ++, 然后我们设置当前的索引的时候,count % banner的size。

面试官说,这样的话,会有一个问题,就是ViewPage 的最后一个页面动画到第一个页面的时候,会执行反向滚动,导致动画异常的问题。

问我怎么解决,我当时没有想出来特别好的方法。

后来,我有时间了,就研究一下,怎么处理这个情况。

其实按照我说的实现方式,会有两个问题:

1.解决最后一个动画到第一个的时候,反向滚动动画异常的问题。
2.你不能左右手动的无限滑动,因为你的思路是元素只有三个。那么滑动到最后一个的时候,你发现不能滑动了。

解决方法

如果我们有三个banner, 那么他的数据长度就是3. 我们假定数据数组为list1

为了实现无线循环,那么我们在PageAdapter 的 getCount 方法,返回的长度是原来的长度(3) + 2, 这样我就会有5 个长度。我们就会有一个数组list2

当instantiateItem 方法调用的时候,如果我们发现position 是0,那么我们就生成list1的最后一个元素对应的页面,如果position 是最后一个位置,那么我们就返回list1第一个元素对应的页面。否则的话,我们就返回list position -1 位置对应的页面。

当我们滑动到最后一个元素的时候,我们偷偷的把当前的index 变为0.这样就又可以从0开始轮播。因为最后一个元素的页面其实和第一个页面是一样的。所以可以没有动画偷偷的替换。

package com.example.widget;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;

/**
 * =======================================================================================
 * 作    者:caoxinyu
 * 创建日期:2020/4/29.
 * 类的作用:
 * 修订历史:
 * =======================================================================================
 */
public class BannerViewAdapter extends PagerAdapter{
    public PagerAdapter mInnerPageAdapter;

    public BannerViewAdapter(PagerAdapter innerPageAdapter) {
        mInnerPageAdapter = innerPageAdapter;
    }

    @Override
    public int getCount() {
        //只有两个以上 才能滚动
        if (mInnerPageAdapter.getCount() > 1) {
            return mInnerPageAdapter.getCount() + 2;
        }else {
            return mInnerPageAdapter.getCount();
        }
    }

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

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        if (position == 0) {
            return mInnerPageAdapter.instantiateItem(container,mInnerPageAdapter.getCount()-1);
        }else if (position == getCount()-1){
            return mInnerPageAdapter.instantiateItem(container,0);
        }
        //因为我们在前面和最后都加了一个元素  所以 当是中间的位置的时候,position 是要减1  给内部的adapter 去创建对象
        return mInnerPageAdapter.instantiateItem(container,position-1);
    }

    @Override
    public void notifyDataSetChanged() {
        mInnerPageAdapter.notifyDataSetChanged();
        super.notifyDataSetChanged();
    }

    //必须要重写的方法 不知道为什么
    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        mInnerPageAdapter.destroyItem(container,position,object);
    }
}

git 项目地址:

https://github.com/TomasYu/androidTest

详见项目的BannerViewPagerFragment 页面实现

参考:
https://juejin.im/post/5d08b8a251882559ed71d789

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值