自动轮播,反转播放的ViewPagerAdapter

作者: 不听话好孩子 | 来源:发表于2017-12-06 17:48 被阅读0次

    支持无限循环,自动轮播,反转播放的ViewPagerAdapter

    触摸暂停切换

    缩放pagertransformer

    无限循环是利用反射设置一个很大的数值来无限循环

    效果

    GIF.gif
    github地址
    GIF.gif

    使用

         LoopFragmentPagerAdapter adapter = new LoopFragmentPagerAdapter(getSupportFragmentManager()) {
    
                @Override
                public int getActualCount() {
                    return 3;
                }
    
                @Override
                public Fragment getActualItem(int position) {
                    return new MyFragment();
                }
    
                @Override
                public CharSequence getActualPagerTitle(int position) {
                    return "标题" + position;
                }
            };
            adapter.setSwitchPeriod(5000);
            //不循环 反转轮播
            adapter.setLoop(false);
            //自动轮播
            adapter.setAutoSwitch(true);
            viewPager.setAdapter(adapter);
    

    代码

    /**
     * Created by 不听话的好孩子 on 2017/12/6.
     * <p>
     * 有RXjava用Rxjava实现切换,无Rxjava用post
     */
    
    public abstract class LoopFragmentPagerAdapter extends FragmentStatePagerAdapter {
        /**
         * 用来启动动画 设置循环
         */
        private boolean isfirst = true;
    
        /**
         * 触摸的时候停止切换
         */
        private boolean touched = false;
    
        /**
         * 切换间隔
         */
        private int switchPeriod = 5000;
    
        /**
         * 自动切换
         */
        private boolean autoSwitch = true;
    
        /**
         * 是否需要无限循环
         */
        private boolean loop = true;
    
        /**
         * post runnable
         */
        private Runnable action;
    
        private int BIGCOUNT = 1000000;
    
        private Disposable disposable;
    
        private boolean reverse;
    
        /**
         * 有无rxjava
         */
        private boolean hasRx;
    
        public LoopFragmentPagerAdapter(FragmentManager fm) {
            super(fm);
        }
    
        @Override
        public Fragment getItem(int position) {
            return getActualItem(position % getActualCount());
        }
    
        @Override
        public void startUpdate(final ViewGroup container) {
            super.startUpdate(container);
            if (isfirst) {
                isfirst = false;
                if (loop) {
                    try {
                        doSettCurrenPager(container);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (autoSwitch) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                        startLoop((ViewPager) container);
                    }
                }
            }
        }
    
        /**
         * 反射设置一个很大的位置达到伪无限循环
         *
         * @param container
         * @throws Exception
         */
        private void doSettCurrenPager(ViewGroup container) throws Exception {
            Field mCurItem = ViewPager.class.getDeclaredField("mCurItem");
            mCurItem.setAccessible(true);
            mCurItem.setInt(container, 1000000 - (BIGCOUNT % getActualCount()));
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return getActualPagerTitle(position % getActualCount());
        }
    
        @Override
        public int getCount() {
            return loop ? Integer.MAX_VALUE : getActualCount();
        }
    
    
        /**
         * 执行循环切换
         *
         * @param viewPager
         */
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        private void startLoop(final ViewPager viewPager) {
            hasRx = checkIfHasRx();
            Log.w("LoopFragmentPager", "startLoop: " + (hasRx ? "当前使用Rxjava" : "当前使用View.post"), null);
            if (!hasRx) {
                usePost(viewPager);
            } else {
                userRx(viewPager);
            }
            viewPager.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                        case MotionEvent.ACTION_MOVE:
                            if (!touched) {
                                touched = true;
                                if (!hasRx) {
                                    viewPager.removeCallbacks(action);
                                }
                            }
                            break;
                        case MotionEvent.ACTION_CANCEL:
                        case MotionEvent.ACTION_UP:
                            touched = false;
                            if (!hasRx) {
                                viewPager.postDelayed(action, switchPeriod);
                            }
                            break;
                    }
                    return false;
                }
            });
            viewPager.getViewTreeObserver().addOnWindowAttachListener(new ViewTreeObserver.OnWindowAttachListener() {
                @Override
                public void onWindowAttached() {
    
                }
    
                @Override
                public void onWindowDetached() {
                    disposable.dispose();
                    viewPager.removeCallbacks(action);
                    action = null;
                    viewPager.getViewTreeObserver().removeOnWindowAttachListener(this);
                    viewPager.setOnTouchListener(null);
                }
            });
    
        }
    
        /**
         * 用Rxjava做循环切换
         *
         * @param viewPager
         */
        private void userRx(final ViewPager viewPager) {
            disposable = Observable.interval(switchPeriod, switchPeriod, TimeUnit.MILLISECONDS)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Long>() {
                        @Override
                        public void accept(Long aLong) throws Exception {
                            if (!touched) {
                                viewPager.setCurrentItem(caculatItem(viewPager));
                            }
                        }
                    });
        }
        /**
         * 用View.post作循环切换
         *
         * @param container
         */
        @SuppressLint("ClickableViewAccessibility")
        private void usePost(final ViewPager container) {
            if (action == null) {
                action = new Runnable() {
                    @Override
                    public void run() {
    
                        container.setCurrentItem(caculatItem(container));
                        container.postDelayed(this, switchPeriod);
                    }
                };
            }
            container.postDelayed(action, switchPeriod);
        }
        private int caculatItem(ViewPager viewPager){
            int nextItem = !reverse ? (viewPager.getCurrentItem() + 1) : (viewPager.getCurrentItem() - 1);
            if (!loop) {
                if (nextItem >= getActualCount()) {
                    reverse = true;
                    nextItem = viewPager.getCurrentItem() - 1;
                }
                if (nextItem < 0) {
                    reverse = false;
                    nextItem = 1;
                }
            }
            return nextItem;
        }
        /**
         * 是否含有Rxjava库
         *
         * @return
         */
        private boolean checkIfHasRx() {
            try {
                Class.forName("io.reactivex.android.schedulers.AndroidSchedulers");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
        public abstract int getActualCount();
    
        public abstract Fragment getActualItem(int position);
    
        public abstract CharSequence getActualPagerTitle(int position);
    }
    
    

    相关文章

      网友评论

        本文标题:自动轮播,反转播放的ViewPagerAdapter

        本文链接:https://www.haomeiwen.com/subject/qrelixtx.html