*** 个人开发中的实例运行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的代码完成。