android - ViewPager:自动播放AutoScrollViewPager、普通的ViewPager 通过ViewPagerIndicator

*** 个人开发中的实例运行demo记录,勿喷 ***

ViewPagerIndicator其实是分为两个部分:indicator(底部的圆点)和ViewPager(上部的内容区域)。

下面写了一个基于ViewPagerIndicator的两个示例,只不过ViewPager不同:上部是自动播放的AutoScrollViewPager,下部是普通的ViewPager,区别在于ViewPager的重写。

先上图:


ViewPagerIndicator的规则图:


代码:

Java代码:负责加载布局和adapter

/**
 * Created by zst on 2016/3/8.
 */
public class HomeFragment extends BaseFragment implements OnRefreshListener {
    private GridView gvFuncs;
    private TextView tvScrollText;
    private LinearLayout llScroll;
    private ViewPager vpBanners;
    private CirclePageIndicator indicatorBanners2;
    private CirclePageIndicator indicatorBanners1;
    private RelativeLayout rlBannersBorder2;
    private RelativeLayout rlBannersBorder1;
    private AutoScrollViewPager asBanners;

    @Override
    public View createSuccessView() {//每次加载的都是缓存数据
        View view = View.inflate(getActivity(), R.layout.home_index_fragment, null);

        gvFuncs = (GridView) view.findViewById(R.id.gv_funcs);
        tvScrollText = (TextView) view.findViewById(R.id.tv_scroll_text);
        llScroll = (LinearLayout) view.findViewById(R.id.ll_scroll);
        vpBanners = (ViewPager) view.findViewById(R.id.vp_banners);
        rlBannersBorder2 = (RelativeLayout) view.findViewById(R.id.rl_banners_border2);
        rlBannersBorder1 = (RelativeLayout) view.findViewById(R.id.rl_banners_border1);
        indicatorBanners2 = (CirclePageIndicator) view.findViewById(R.id.indicator_banners2);
        indicatorBanners1 = (CirclePageIndicator) view.findViewById(R.id.indicator_banners1);
        asBanners = (AutoScrollViewPager) view.findViewById(R.id.as_banners);

        initData();

        return view;
    }

    /* init Data */
    private void initData() {

        //设置Adapter等
        gvFuncs.setAdapter(new FuncsAdapter(getActivity(), funcsList));//设置GridView

        //能轮播的viewpager
        asBanners.startAutoScroll();
        asBanners.setAdapter(new BannersAdapter(getActivity(), bannersList));
        rlBannersBorder1.setLayoutParams(new LinearLayout.LayoutParams(UiUtils.getScreenWidth(), UiUtils.getPicShowHeight()));
        indicatorBanners1.setViewPager(asBanners);
        indicatorBanners1.setSnap(true);

        //不能轮播的viewpager
        vpBanners.setAdapter(new BannersAdapter(getActivity(), bannersList));
        rlBannersBorder2.setLayoutParams(new LinearLayout.LayoutParams(UiUtils.getScreenWidth(), UiUtils.getPicShowHeight()));
        indicatorBanners2.setViewPager(vpBanners);
        indicatorBanners2.setSnap(false);<span style="color:#808080;">//圆点由第一个经过间隙移动到第二个,有明显的动画
        //需要修改圆点之间的间隙大小,必须改ViewPagerIndicator框架的CirclePageIndicator类的final float threeRadius = mRadius * 3;//3改大一点即可

</span>       //设置监听
        addListener();
    }

    /* 监听类 */
    private void addListener() {
        //GridView Funcs监听类
        gvFuncs.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                UiUtils.showToast(funcsList.get(position).click);
            }
        });
    }

}

布局xml:上部是播放的ViewPager,下部是普通的ViewPager

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/home_bg">

    <RelativeLayout
            android:id="@+id/rl_banners_border1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <com.baofoo.mobile.wallet.common.view.AutoScrollViewPager
                android:id="@+id/as_banners"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        <com.viewpagerindicator.CirclePageIndicator
                android:id="@+id/indicator_banners1"
                android:padding="10dip"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="10dp"
                android:layout_height="wrap_content"
                android:layout_width="fill_parent"/>
    </RelativeLayout>

    <RelativeLayout
            android:id="@+id/rl_banners_border2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <android.support.v4.view.ViewPager
                android:id="@+id/vp_banners"
                android:layout_width="fill_parent"
                android:layout_height="match_parent"/>

        <com.viewpagerindicator.CirclePageIndicator
                android:id="@+id/indicator_banners2"
                android:padding="10dip"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="10dp"
                android:layout_height="wrap_content"
                android:layout_width="fill_parent"/>
    </RelativeLayout>
</LinearLayout>

Adapter:主要决定ViewPager里面显示什么内容,这里自动播放和普通的使用的是同一个Adapter

public class BannersAdapter extends PagerAdapter {
    private Activity activity;
    private List<Banners> bannersList;
    private ImageLoader imageLoader;
    private DisplayImageOptions options;

    public BannersAdapter(Activity activity, List<Banners> bannersList) {
        this.activity = activity;
        this.bannersList = bannersList;

        imageLoader = ImageLoader.getInstance();
        options = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();
    }


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

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ImageView imageView = new ImageView(activity);
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);// 基于控件大小填充图片
        imageLoader.displayImage(bannersList.get(position).img, imageView, options);
        LogUtils.d("aaaaaaaaaaaaaaa"+bannersList.get(position).img);
        container.addView(imageView);

        return imageView;
    }

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

重写的ViewPager,包括两个文件:AutoScrollViewPager、CustomDurationScroller,在git上可找到:https://github.com/Trinea/android-auto-scroll-view-pager

AutoScrollViewPager代码:

package com.baofoo.mobile.wallet.common.view;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Interpolator;

/**
 * Auto Scroll View Pager
 * 
 * Created by zst on 2016/3/16.
 */
public class AutoScrollViewPager extends ViewPager {

    public static final int        DEFAULT_INTERVAL            = 1500;

    public static final int        LEFT                        = 0;
    public static final int        RIGHT                       = 1;

    /** do nothing when sliding at the last or first item **/
    public static final int        SLIDE_BORDER_MODE_NONE      = 0;
    /** cycle when sliding at the last or first item **/
    public static final int        SLIDE_BORDER_MODE_CYCLE     = 1;
    /** deliver event to parent when sliding at the last or first item **/
    public static final int        SLIDE_BORDER_MODE_TO_PARENT = 2;

    /** auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL} **/
    private long                   interval                    = DEFAULT_INTERVAL;
    /** auto scroll direction, default is {@link #RIGHT} **/
    private int                    direction                   = RIGHT;
    /** whether automatic cycle when auto scroll reaching the last or first item, default is true **/
    private boolean                isCycle                     = true;
    /** whether stop auto scroll when touching, default is true **/
    private boolean                stopScrollWhenTouch         = true;
    /** how to process when sliding at the last or first item, default is {@link #SLIDE_BORDER_MODE_NONE} **/
    private int                    slideBorderMode             = SLIDE_BORDER_MODE_NONE;
    /** whether animating when auto scroll at the last or first item **/
    private boolean                isBorderAnimation           = true;
    /** scroll factor for auto scroll animation, default is 1.0 **/
    private double                 autoScrollFactor            = 1.0;
    /** scroll factor for swipe scroll animation, default is 1.0 **/
    private double                 swipeScrollFactor           = 1.0;

    private Handler                handler;
    private boolean                isAutoScroll                = false;
    private boolean                isStopByTouch               = false;
    private float                  touchX                      = 0f, downX = 0f;
    private CustomDurationScroller scroller                    = null;

    public static final int        SCROLL_WHAT                 = 0;

    public AutoScrollViewPager(Context paramContext) {
        super(paramContext);
        init();
    }

    public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
        super(paramContext, paramAttributeSet);
        init();
    }

    private void init() {
        handler = new MyHandler(this);
        setViewPagerScroller();
    }

    /**
     * start auto scroll, first scroll delay time is {@link #getInterval()}
     */
    public void startAutoScroll() {
        isAutoScroll = true;
        sendScrollMessage((long)(interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
    }

    /**
     * start auto scroll
     * 
     * @param delayTimeInMills first scroll delay time
     */
    public void startAutoScroll(int delayTimeInMills) {
        isAutoScroll = true;
        sendScrollMessage(delayTimeInMills);
    }

    /**
     * stop auto scroll
     */
    public void stopAutoScroll() {
        isAutoScroll = false;
        handler.removeMessages(SCROLL_WHAT);
    }

    /**
     * set the factor by which the duration of sliding animation will change while swiping
     */
    public void setSwipeScrollDurationFactor(double scrollFactor) {
        swipeScrollFactor = scrollFactor;
    }

    /**
     * set the factor by which the duration of sliding animation will change while auto scrolling
     */
    public void setAutoScrollDurationFactor(double scrollFactor) {
        autoScrollFactor = scrollFactor;
    }

    private void sendScrollMessage(long delayTimeInMills) {
        /** remove messages before, keeps one message is running at most **/
        handler.removeMessages(SCROLL_WHAT);
        handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
    }

    /**
     * set ViewPager scroller to change animation duration when sliding
     */
    private void setViewPagerScroller() {
        try {
            Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
            scrollerField.setAccessible(true);
            Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
            interpolatorField.setAccessible(true);

            scroller = new CustomDurationScroller(getContext(), (Interpolator)interpolatorField.get(null));
            scrollerField.set(this, scroller);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * scroll only once
     */
    public void scrollOnce() {
        PagerAdapter adapter = getAdapter();
        int currentItem = getCurrentItem();
        int totalCount;
        if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
            return;
        }

        int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
        if (nextItem < 0) {
            if (isCycle) {
                setCurrentItem(totalCount - 1, isBorderAnimation);
            }
        } else if (nextItem == totalCount) {
            if (isCycle) {
                setCurrentItem(0, isBorderAnimation);
            }
        } else {
            setCurrentItem(nextItem, true);
        }
    }

    /**
     * <ul>
     * if stopScrollWhenTouch is true
     * <li>if event is down, stop auto scroll.</li>
     * <li>if event is up, start auto scroll again.</li>
     * </ul>
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = MotionEventCompat.getActionMasked(ev);

        if (stopScrollWhenTouch) {
            if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
                isStopByTouch = true;
                stopAutoScroll();
            } else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
                startAutoScroll();
            }
        }

        if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) {
            touchX = ev.getX();
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                downX = touchX;
            }
            int currentItem = getCurrentItem();
            PagerAdapter adapter = getAdapter();
            int pageCount = adapter == null ? 0 : adapter.getCount();
            /**
             * current index is first one and slide to right or current index is last one and slide to left.<br/>
             * if slide border mode is to parent, then requestDisallowInterceptTouchEvent false.<br/>
             * else scroll to last one when current item is first one, scroll to first one when current item is last
             * one.
             */
            if ((currentItem == 0 && downX <= touchX) || (currentItem == pageCount - 1 && downX >= touchX)) {
                if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else {
                    if (pageCount > 1) {
                        setCurrentItem(pageCount - currentItem - 1, isBorderAnimation);
                    }
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                return super.dispatchTouchEvent(ev);
            }
        }
        getParent().requestDisallowInterceptTouchEvent(true);

        return super.dispatchTouchEvent(ev);
    }

    private static class MyHandler extends Handler {

        private final WeakReference<AutoScrollViewPager> autoScrollViewPager;

        public MyHandler(AutoScrollViewPager autoScrollViewPager) {
            this.autoScrollViewPager = new WeakReference<AutoScrollViewPager>(autoScrollViewPager);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case SCROLL_WHAT:
                    AutoScrollViewPager pager = this.autoScrollViewPager.get();
                    if (pager != null) {
                        pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
                        pager.scrollOnce();
                        pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
                        pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
                    }
                default:
                    break;
            }
        }
    }

    /**
     * get auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
     * 
     * @return the interval
     */
    public long getInterval() {
        return interval;
    }

    /**
     * set auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
     * 
     * @param interval the interval to set
     */
    public void setInterval(long interval) {
        this.interval = interval;
    }

    /**
     * get auto scroll direction
     * 
     * @return {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
     */
    public int getDirection() {
        return (direction == LEFT) ? LEFT : RIGHT;
    }

    /**
     * set auto scroll direction
     * 
     * @param direction {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
     */
    public void setDirection(int direction) {
        this.direction = direction;
    }

    /**
     * whether automatic cycle when auto scroll reaching the last or first item, default is true
     * 
     * @return the isCycle
     */
    public boolean isCycle() {
        return isCycle;
    }

    /**
     * set whether automatic cycle when auto scroll reaching the last or first item, default is true
     * 
     * @param isCycle the isCycle to set
     */
    public void setCycle(boolean isCycle) {
        this.isCycle = isCycle;
    }

    /**
     * whether stop auto scroll when touching, default is true
     * 
     * @return the stopScrollWhenTouch
     */
    public boolean isStopScrollWhenTouch() {
        return stopScrollWhenTouch;
    }

    /**
     * set whether stop auto scroll when touching, default is true
     * 
     * @param stopScrollWhenTouch
     */
    public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
        this.stopScrollWhenTouch = stopScrollWhenTouch;
    }

    /**
     * get how to process when sliding at the last or first item
     * 
     * @return the slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
     *         {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
     */
    public int getSlideBorderMode() {
        return slideBorderMode;
    }

    /**
     * set how to process when sliding at the last or first item
     * 
     * @param slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
     *        {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
     */
    public void setSlideBorderMode(int slideBorderMode) {
        this.slideBorderMode = slideBorderMode;
    }

    /**
     * whether animating when auto scroll at the last or first item, default is true
     * 
     * @return
     */
    public boolean isBorderAnimation() {
        return isBorderAnimation;
    }

    /**
     * set whether animating when auto scroll at the last or first item, default is true
     * 
     * @param isBorderAnimation
     */
    public void setBorderAnimation(boolean isBorderAnimation) {
        this.isBorderAnimation = isBorderAnimation;
    }
}
CustomDurationScroller代码:

package com.baofoo.mobile.wallet.common.view;

import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;

/**
 * CustomDurationScroller
 * 
 * Created by zst on 2016/3/16.
 */
public class CustomDurationScroller extends Scroller {

    private double scrollFactor = 1;

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

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

    /**
     * not exist in android 2.3
     * 
     * @param context
     * @param interpolator
     * @param flywheel
     */
    // @SuppressLint("NewApi")
    // public CustomDurationScroller(Context context, Interpolator interpolator, boolean flywheel){
    // super(context, interpolator, flywheel);
    // }

    /**
     * Set the factor by which the duration will change
     */
    public void setScrollDurationFactor(double scrollFactor) {
        this.scrollFactor = scrollFactor;
    }

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


其中AutoScrollViewPager设置:

1. 启动ViewPager自动滚动

startAutoScroll() 启动自动滚动
stopAutoScroll() 停止自动滚动

 

2. 设置

setInterval(long) 设置自动滚动的间隔时间,单位为毫秒
setDirection(int) 设置自动滚动的方向,默认向右
setCycle(boolean) 是否自动循环轮播,默认为true

setScrollDurationFactor(double) 设置ViewPager滑动动画间隔时间的倍率,达到减慢动画或改变动画速度的效果
setStopScrollWhenTouch(boolean) 当手指碰到ViewPager时是否停止自动滚动,默认为true
setSlideBorderMode(int) 滑动到第一个或最后一个Item的处理方式,支持没有任何操作、轮播以及传递到父View三种模式

setBorderAnimation(boolean) 设置循环滚动时滑动到从边缘滚动到下一个是否需要动画,默认为true

viewpagerindicator设置:

        indicator_banners.setPageColor(0xFFFFFFFF);//圆圈没有选中的颜色
        indicator_banners.setFillColor(0xFFFA7298);//圆圈被选中的颜色
        indicator_banners.setStrokeColor(0x00000000);//圆圈边框色,这里是透明
        indicator_banners.setSnap(false);
        indicator_banners.layout(0,0,10,5);

还有其它设置可以看官方demo


至此两个ViewPager的代码完成。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Beluga_白鲸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值