Android--ViewPager----完美轮播
2016-07-01 17:37
399 查看
效果图:
一:代码使用
MainActivity:
activity_main:
TimePagerAdapter:
二:实现
RecycleGBin:
CustomDurationScoller:
RecyclingPagerAdapter:
ImagePagerApater:
AutoScrollViewPager:
ListUtil:工具类:
三:实现:
1–:并没有使用线程池或者定时器定时执行任务状态,而是通过Handler发送消息来完成滚动,在完成滚动之后,再发送一个消息delay:
2–:对于ViewPager嵌套导致子ViewPager无法触摸问题通过在子ViewPager中:
禁止父控件对TouchEvent控制的。
3–:ViewPager的滑动是通过反射方式重新设置Scroller,改变startScroll的间隔时间完成的。
调用如下方法可以完成设置:
四:设置
一:代码使用
MainActivity:
public class MainActivity extends AppCompatActivity { String url = "https://img1.doubanio.com/view/photo/photo/public/p2328130909.jpg"; List<String> urls = new ArrayList<>(); AutoScrollViewPager viewPager; LinearLayout container; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initImage(); } public void initImage() { viewPager = (AutoScrollViewPager) findViewById(R.id.viewpager); container = (LinearLayout) findViewById(R.id.container); urls.add(url); urls.add(url); urls.add(url); urls.add(url); showTimeWheel(urls); } public void showTimeWheel(List<String> urls) { viewPager.setAdapter(new TimePagerAdapter(this, urls)); viewPager.setOnPointIndex(urls.size(), container); //开始滚动 viewPager.startAutoScroll(); } @Override public void onPause() { super.onPause(); viewPager.stopAutoScroll(); } @Override public void onResume() { super.onResume(); viewPager.startAutoScroll(); } }
activity_main:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.erhu.myviewpager.MainActivity"> <com.erhu.view.AutoScrollViewPager android:id="@+id/viewpager" android:src="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="40px" android:layout_alignParentBottom="true" android:gravity="center" android:orientation="horizontal" /> </RelativeLayout>
TimePagerAdapter:
public class TimePagerAdapter extends ImagePagerAdapter<String> { Context context; public TimePagerAdapter(Context context, List<String> urls) { super(context, urls); this.context = context; } @Override public void setImageView(ImageView imageView, String coupon) { // 使用ImageLoader进行图片下载 ImageLoader.getInstance().displayImage(coupon, imageView); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //针对每个view的图片操作 } }); } }
二:实现
RecycleGBin:
public class RecycleBin { private View[] activeViews = new View[0]; private int[] activeViewTypes = new int[0]; private SparseArray<View>[] scrapViews; private int viewTypeCount; private SparseArray<View> currentScrapViews; public void setViewTypeCount(int viewTypeCount) { if (viewTypeCount < 1) { throw new IllegalArgumentException("Can't have a viewTypeCount < 1"); } SparseArray<View>[] scrapViews = new SparseArray[viewTypeCount]; for (int i = 0; i < viewTypeCount; i++) { scrapViews[i] = new SparseArray<View>(); } this.viewTypeCount = viewTypeCount; currentScrapViews = scrapViews[0]; this.scrapViews = scrapViews; } protected boolean shouldRecycleViewType(int viewType) { return viewType >= 0; } View getScrapView(int position, int viewType) { if (viewTypeCount == 1) { return retrieveFromScrap(currentScrapViews, position); } else if (viewType >= 0 && viewType < scrapViews.length) { return retrieveFromScrap(scrapViews[viewType], position); } return null; } void addScrapView(View scrap, int position, int viewType) { if (viewTypeCount == 1) { currentScrapViews.put(position, scrap); } else { scrapViews[viewType].put(position, scrap); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { scrap.setAccessibilityDelegate(null); } } void scrapActiveViews() { final View[] activeViews = this.activeViews; final int[] activeViewTypes = this.activeViewTypes; final boolean multipleScraps = viewTypeCount > 1; SparseArray<View> scrapViews = currentScrapViews; final int count = activeViews.length; for (int i = count - 1; i >= 0; i--) { final View victim = activeViews[i]; if (victim != null) { int whichScrap = activeViewTypes[i]; activeViews[i] = null; activeViewTypes[i] = -1; if (!shouldRecycleViewType(whichScrap)) { continue; } if (multipleScraps) { scrapViews = this.scrapViews[whichScrap]; } scrapViews.put(i, victim); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { victim.setAccessibilityDelegate(null); } } } pruneScrapViews(); } private void pruneScrapViews() { final int maxViews = activeViews.length; final int viewTypeCount = this.viewTypeCount; final SparseArray<View>[] scrapViews = this.scrapViews; for (int i = 0; i < viewTypeCount; ++i) { final SparseArray<View> scrapPile = scrapViews[i]; int size = scrapPile.size(); final int extras = size - maxViews; size--; for (int j = 0; j < extras; j++) { scrapPile.remove(scrapPile.keyAt(size--)); } } } static View retrieveFromScrap(SparseArray<View> scrapViews, int position) { int size = scrapViews.size(); if (size > 0) { for (int i = 0; i < size; i++) { int fromPosition = scrapViews.keyAt(i); View view = scrapViews.get(fromPosition); if (fromPosition == position) { scrapViews.remove(fromPosition); return view; } } int index = size - 1; View r = scrapViews.valueAt(index); scrapViews.remove(scrapViews.keyAt(index)); return r; } else { return null; } } }
CustomDurationScoller:
public class CustomDurationScroller extends Scroller { private double scrollFactor =2; public CustomDurationScroller(Context context) { super(context); } public CustomDurationScroller(Context context, Interpolator interpolator) { super(context, interpolator); } 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)); } }
RecyclingPagerAdapter:
public abstract class RecyclingPagerAdapter extends PagerAdapter { static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE; private final RecycleBin recycleBin; public RecyclingPagerAdapter() { this(new RecycleBin()); } RecyclingPagerAdapter(RecycleBin recycleBin) { this.recycleBin = recycleBin; recycleBin.setViewTypeCount(getViewTypeCount()); } @Override public void notifyDataSetChanged() { recycleBin.scrapActiveViews(); super.notifyDataSetChanged(); } @Override public final Object instantiateItem(ViewGroup container, int position) { int viewType = getItemViewType(position); View view = null; if (viewType != IGNORE_ITEM_VIEW_TYPE) { view = recycleBin.getScrapView(position, viewType); } view = getView(position, view, container); container.addView(view); return view; } @Override public final void destroyItem(ViewGroup container, int position, Object object) { View view = (View) object; container.removeView(view); int viewType = getItemViewType(position); if (viewType != IGNORE_ITEM_VIEW_TYPE) { recycleBin.addScrapView(view, position, viewType); } } @Override public final boolean isViewFromObject(View view, Object object) { return view == object; } public int getViewTypeCount() { return 1; } public int getItemViewType(int position) { return 0; } public abstract View getView(int position, View convertView, ViewGroup container); }
ImagePagerApater:
public abstract class ImagePagerAdapter<T> extends RecyclingPagerAdapter { private Context context; private List<T> listDatas; private int size; private boolean isInfiniteLoop;//是否开启无限循环 public ImagePagerAdapter(Context context, List<T> listDatas) { this.context = context; this.listDatas = listDatas; this.size = ListUtil.getCount(listDatas); //大于1时,启动轮播 isInfiniteLoop = !(ListUtil.isNotEmpty(listDatas) && listDatas.size() == 1); } /** * @param isInfiniteLoop 是否开启无限循环 默认>1时开启 */ public ImagePagerAdapter(Context context, List<T> listDatas, boolean isInfiniteLoop) { this.context = context; this.listDatas = listDatas; this.size = ListUtil.getCount(listDatas); this.isInfiniteLoop = isInfiniteLoop; } @Override public int getCount() { return isInfiniteLoop ? Integer.MAX_VALUE : ListUtil.getCount(listDatas); } private int getPosition(int position) { return isInfiniteLoop ? position % size : position; } @Override public View getView(int position, View view, ViewGroup container) { ViewHolder holder; if (view == null) { holder = new ViewHolder(); view = holder.imageView = new ImageView(context); holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } setImageView(holder.imageView, listDatas.get(getPosition(position))); return view; } public abstract void setImageView(ImageView imageView, T t); private static class ViewHolder { ImageView imageView; } public Context getContext() { return context; } public void setContext(Context context) { this.context = context; } }
AutoScrollViewPager:
public class AutoScrollViewPager extends ViewPager { public static final int DEFAULT_INTERVAL = 4000;//默认的时间间隔 public static final int LEFT = 0; public static final int RIGHT = 1; public static final int SLIDE_BORDER_MODE_NONE = 0; public static final int SLIDE_BORDER_MODE_CYCLE = 1; public static final int SLIDE_BORDER_MODE_TO_PARENT = 2; private long interval = DEFAULT_INTERVAL; private int direction = RIGHT; private boolean isCycle = true; private boolean stopScrollWhenTouch = true; private int slideBorderMode = SLIDE_BORDER_MODE_NONE; private boolean isBorderAnimation = true; private Handler handler; private boolean isAutoScroll = true; 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(); setViewPagerScroller(); } public void startAutoScroll() { isAutoScroll = true; sendScrollMessage(interval); } public void startAutoScroll(int delayTimeInMills) { isAutoScroll = true; sendScrollMessage(delayTimeInMills); } public void stopAutoScroll() { isAutoScroll = false; handler.removeMessages(SCROLL_WHAT); } public void setScrollDurationFactor(double scrollFactor) { scroller.setScrollDurationFactor(scrollFactor); } private void sendScrollMessage(long delayTimeInMills) { handler.removeMessages(SCROLL_WHAT); handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills); } 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(); } } 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); } } @Override public boolean onTouchEvent(MotionEvent ev) { if (stopScrollWhenTouch) { if (ev.getAction() == 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(); 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.onTouchEvent(ev); } } getParent().requestDisallowInterceptTouchEvent(true); return super.onTouchEvent(ev); } public class MyHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case SCROLL_WHAT: scrollOnce(); sendScrollMessage(interval); break; default: break; } } } public long getInterval() { return interval; } public void setInterval(long interval) { this.interval = interval; } public int getDirection() { return (direction == LEFT) ? LEFT : RIGHT; } public void setDirection(int direction) { this.direction = direction; } public boolean isCycle() { return isCycle; } public void setCycle(boolean isCycle) { this.isCycle = isCycle; } public boolean isStopScrollWhenTouch() { return stopScrollWhenTouch; } public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) { this.stopScrollWhenTouch = stopScrollWhenTouch; } public int getSlideBorderMode() { return slideBorderMode; } public void setSlideBorderMode(int slideBorderMode) { this.slideBorderMode = slideBorderMode; } public boolean isBorderAnimation() { return isBorderAnimation; } public void setBorderAnimation(boolean isBorderAnimation) { this.isBorderAnimation = isBorderAnimation; } private LinearLayout container;//点的父布局 private LinearLayout.LayoutParams paramsSmall;//小点属性 private List<View> points;//点集合 private int size;// 实际item个数 private int pointNormal;//没有选中的点drawable private int pointSelect;//选中的点drawable public void setOnPointIndex(int size, LinearLayout container, int pointNormal, int pointSelect) { this.size = size; this.container = container; this.pointNormal = pointNormal; this.pointSelect = pointSelect; //大于1,才显示point 进行轮播 if (this.container == null) { stopAutoScroll(); return; } if (this.size <= 1) { stopAutoScroll(); this.container.setVisibility(GONE); return; } points = new ArrayList<>(); paramsSmall = new LinearLayout.LayoutParams(20, 20); paramsSmall.setMargins(10, 10, 10, 10); setPoint(); addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { initPointColor(getCurrentItem()); } @Override public void onPageScrollStateChanged(int state) { } }); } public void setOnPointIndex(int size, LinearLayout container) { setOnPointIndex(size, container, R.mipmap.ic_point_pre_3x, R.mipmap.ic_point_3x); } private void setPoint() { container.removeAllViews(); points.clear(); for (int i = 0; i < size; i++) { View view = new View(getContext());//点 view.setLayoutParams(paramsSmall); container.addView(view); points.add(view); } initPointColor(0); } //初始化底部指示点颜色 public void initPointColor(int index) { for (int i = 0; i < size; i++) { points.get(i).setBackgroundResource(pointNormal); points.get(i).setLayoutParams(paramsSmall); } points.get(index % size).setBackgroundResource(pointSelect); points.get(index % size).setLayoutParams(paramsSmall); } }
ListUtil:工具类:
/** * List工具类 */ public class ListUtil { /** * 判断集合list数据是否为空 */ public static boolean isEmpty(List<?> list) { if (list == null || list.size() == 0) return true; return false; } /** * 判断集合list数据是否为非空 */ public static <T> boolean isNotEmpty(List<T> list) { return !isEmpty(list); } /** * 清空集合 */ public static void clearList(List<?> list) { if (!isEmpty(list)) { list.clear(); } } /** * 获取集合list数据长度 */ public static <T> int getCount(List<T> list) { return list == null ? 0 : list.size(); } }
三:实现:
1–:并没有使用线程池或者定时器定时执行任务状态,而是通过Handler发送消息来完成滚动,在完成滚动之后,再发送一个消息delay:
public class MyHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case SCROLL_WHAT: scrollOnce(); sendScrollMessage(interval); break; default: break; } } } 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); } } private void sendScrollMessage(long delayTimeInMills) { handler.removeMessages(SCROLL_WHAT); handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills); } public void startAutoScroll(int delayTimeInMills) { isAutoScroll = true; sendScrollMessage(delayTimeInMills); }
2–:对于ViewPager嵌套导致子ViewPager无法触摸问题通过在子ViewPager中:
getParent().requestDisallowInterceptTouchEvent(true);
禁止父控件对TouchEvent控制的。
3–:ViewPager的滑动是通过反射方式重新设置Scroller,改变startScroll的间隔时间完成的。
调用如下方法可以完成设置:
public void setScrollDurationFactor(double scrollFactor) { scroller.setScrollDurationFactor(scrollFactor); }
四:设置
setInterval(long) 设置自动滚动的间隔时间,单位为毫秒 setDirection(int) 设置自动滚动的方向,默认向右 setCycle(boolean) 是否自动循环轮播,默认为true setScrollDurationFactor(double) 设置ViewPager滑动动画间隔时间的倍率,达到减慢动画或改变动画速度的效果 setStopScrollWhenTouch(boolean) 当手指碰到ViewPager时是否停止自动滚动,默认为true setSlideBorderMode(int) 滑动到第一个或最后一个Item的处理方式,支持没有任何操作、轮播以及传递到父View三种模式 setBorderAnimation(boolean) 设置循环滚动时滑动到从边缘滚动到下一个是否需要动画,默认为true
相关文章推荐
- Android之获取手机上的图片和视频缩略图thumbnails
- android string.xml文件中的整型和string型代替
- Android java 与 javascript互访(相互调用)的方法例子
- android上改变listView的选中颜色
- String.intern
- Prototype源码浅析 String部分(二)
- Ruby中的String对象学习笔记
- C#.Net ArrayList的使用方法
- PostgreSQL ERROR: invalid escape string 解决办法
- VBS ArrayList Class vbs中的数组类
- 浅谈C++中的string 类型占几个字节
- 标准C++类string的Copy-On-Write技术
- C++实现string存取二进制数据的方法
- C#中string和StingBuilder内存中的区别实例分析
- 详解C++中实现继承string类的MyString类的步骤
- PHP STRING 陷阱原理说明
- c#中 String和string的区别介绍
- C#中数组Array,ArrayList,泛型List详细对比
- C#实现的图片、string相互转换类分享
- asp.net String.IsNullOrEmpty 方法