Android ViewPager+Handler 实现简易无限轮播

有现成的还是用现成的吧 毕竟别人都封装好了

方式一

缺点
自动滑动到最后一张时继续滑动会闪一下, 效果不好, ,阔以设置滑动速度, ,让每次滑动都立刻到下一张

思路
假设有三张图片a, b, c, 当滑动到 c 时, 如果直接使用 viewpager 的setCurrentItem方法跳到 a 时, c 就无法正常显示; 因此可以在 c 后面加一张 a1, 当滑动到 c 时可以继续滑动, 当滑动到 a1 时使用 setCurrentItem方法跳到 a 即可. 同理, 为避免上述问题应该在 a 前加一张 c1, 并设置初始位置为1, 当初次运行程序时向左滑动, 滑动到 c1 使用setCurrentItem方法跳到 c 即可.

自动轮播实现思路
使用sendEmptyMessageDelayed方法实现定时发送

直接复制

adapter

    private class ViewPagerAdapter extends PagerAdapter{

        private List<Integer> imgs;

        public ViewPagerAdapter(List<Integer> imgs){
            this.imgs = imgs;
        }

        @Override
        public int getCount() {
            return imgs.size();
        }

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

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
//            super.destroyItem(container, position, object);
            container.removeView((View) object);
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            ImageView imageView = new ImageView(MainActivity.this);
            imageView.setImageResource(imgs.get(position));
            container.addView(imageView);
            return imageView;
        }
    }

设置滑动速度

    public class ViewPagerScroller extends Scroller {
        private int mScrollDuration = 0;             // 滑动速度

        /**
         * 设置速度速度
         * @param duration
         */
        public void setScrollDuration(int duration){
            this.mScrollDuration = duration;
        }

        public ViewPagerScroller(Context context) {
            super(context);
        }

        public ViewPagerScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }

        public ViewPagerScroller(Context context, Interpolator interpolator, boolean flywheel) {
            super(context, interpolator, flywheel);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, mScrollDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            super.startScroll(startX, startY, dx, dy, mScrollDuration);
        }

        public void initViewPagerScroll(ViewPager viewPager) {
            try {
                Field mScroller = ViewPager.class.getDeclaredField("mScroller");
                mScroller.setAccessible(true);
                mScroller.set(viewPager, this);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

activity

private ViewPager viewPager;
    private List<Integer> imgs = new ArrayList<>();

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1){
                viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
                handler.sendEmptyMessageDelayed(1, 2000);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = findViewById(R.id.m_view_pager);

        imgs.add(R.drawable.zzz);
        imgs.add(R.drawable.kkk);
        imgs.add(R.drawable.lll);
        imgs.add(R.drawable.zzz);
        imgs.add(R.drawable.kkk);

        ViewPagerScroller scroller = new ViewPagerScroller(this);
        scroller.setScrollDuration(150);//设置滑动时间为150毫秒
        scroller.initViewPagerScroll(viewPager);
        viewPager.setAdapter(new ViewPagerAdapter(imgs));
        viewPager.setCurrentItem(1);
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (position == 0){
                    viewPager.setCurrentItem(imgs.size() - 2);
                    return;
                }
                if (position == (imgs.size() - 1)){
                    viewPager.setCurrentItem(1);
                    return;
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
        handler.sendEmptyMessageDelayed(1, 2000);
    }

方式二

思路
设置adapter返回一个无限大的值, 当滑动到大于集合/数组数量时进行取余

缺点
,,第一次进入界面开始轮播后无法向左滑动,,不过看CSDN官方软件也是这样的,,(手动狗头)

自动轮播和方式一思路一致

举个栗子
语言为kotlin, 接口为WanAndroid主页轮播

ViewPagerAdapter

class ViewPagerAdapter(
    context: Context,
    list: ArrayList<BannerData>
): PagerAdapter() {

    private var mClick: OnItemClick<BannerData>? = null

    private var mContext: Context? = null
    private var bannerData: MutableList<BannerData>? = null

    init {
        mContext = context
        bannerData = list
    }

    fun setClick(mClick: OnItemClick<BannerData>){
        this.mClick = mClick
    }

    override fun isViewFromObject(view: View, `object`: Any): Boolean = view == `object`

    override fun getItemPosition(`object`: Any): Int = POSITION_NONE

    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
        container.removeView(`object` as View?)
    }

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        val imgView = ImageView(mContext)
        if (bannerData!!.isNotEmpty()){
            val imgUrl = bannerData!![position % bannerData!!.size].imagePath
            imgView.setOnClickListener { mClick?.itemClick(bannerData!![position % bannerData!!.size], position) }
            Glide.with(container).load(imgUrl).into(imgView)
        }
        container.addView(imgView)
        return imgView
    }
}

页面使用碎片

class HomePage: BaseFragment(), OnItemClick<BannerData> {

    private var homeModelImpl = HomeModelImpl()
    private val handlerBanner = Config.HOME_BANNER
    private var adapter: ViewPagerAdapter? = null

    private var handler = Handler{
        when (it.what){
            handlerBanner -> {
                home_banner.currentItem = position + 1
            }
        }
        false
    }

    private var bannerData = ArrayList<BannerData>()
    private var position = 0

    override fun layout(): Int = R.layout.main_home_page

    override fun initData() {
        home_banner.addOnPageChangeListener(pageChangeListener)
        homeModelImpl.getBanner(object: CallbackView<BannerBean> {
            override fun onSuccess(t: BannerBean) {
                bannerData.clear()
                bannerData.addAll(t.data)
                adapter = ViewPagerAdapter(context!!, bannerData)
                adapter!!.setClick(this@HomePage)
                home_banner.adapter = adapter
                LogUtils.i("Success! adapter is notify data set changed")
                handler.sendEmptyMessageDelayed(handlerBanner, 3000)
            }

            override fun onFail(throwable: Throwable) {
                LogUtils.e("Fail: " + throwable.message)
            }

            override fun onError(code: Int) {
                LogUtils.e("Error code = $code")
            }
        })
    }

    private var pageChangeListener: ViewPager.OnPageChangeListener = object: ViewPager.OnPageChangeListener{
        override fun onPageScrollStateChanged(state: Int) {
            if (state == 1){//手指触摸
                handler.removeMessages(handlerBanner)
            }else if (state == 0){//滑动结束
                handler.sendEmptyMessageDelayed(handlerBanner, 3000)
            }
        }

        override fun onPageScrolled(
            position: Int,
            positionOffset: Float,
            positionOffsetPixels: Int
        ) {}

        override fun onPageSelected(i: Int) {
            position = i
//            LogUtils.e("Page selected position = $i")
        }
    }

    override fun itemClick(t: BannerData, position: Int) {
        LogUtils.i(t.title)
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeMessages(handlerBanner)
    }
}

推荐阅读: ViewPager2: 打造Banner控件

发布了13 篇原创文章 · 获赞 2 · 访问量 1074

猜你喜欢

转载自blog.csdn.net/AneTist/article/details/104170425