Android ViewPager实现智能无限循环滚动回绕效果

Android ViewPager实现智能无限循环滚动回绕效果,第1张

概述android系统提供的ViewPager标准方式是左右可以自由滑动,但是滑动到最左边的极限位置是第一个page,滑动到最右边的位置是最后一个page,当滑动到最左或者最右时候,就不能再滑动/滚动了,这是Android系统默认的View

androID系统提供的VIEwPager标准方式是左右可以自由滑动,但是滑动到最左边的极限位置是第一个page,滑动到最右边的位置是最后一个page,当滑动到最左或者最右时候,就不能再滑动/滚动了,这是AndroID系统默认的VIEwPager实现方式。 

但是有些情况下开发者可能希望VIEwPager能够智能的无限循环滚动回绕,比如现在总共有编号1,2,3,4,5的5个Page。 

(1)当用户手指从右往左滚动到最右边/最后面的页面5时候,如果此时用户继续拖住VIEwPager往左边滑动,那么VIEwPager将回绕、循环到第一个Page -> 1,接着就是2,5;

 (2)反过来,如果当用户手指从左往右,滑到最左边的第一个Page:1时候,如果此时继续拖住VIEwPager继续从左往右滑动,那么将回绕到5,接着就是4,1.

我们把这种VIEwPager称之谓“无限循环滚动回绕”的VIEwPager。 

这种类型的VIEwPager网上有较多实现方式,现在给出一个流程较广的代码实现。 

写一个测试的MainActivity.Java:

package zhangphil.demo;import java.util.Random;import androID.app.Activity;import androID.graphics.color;import androID.os.Bundle;import androID.support.v4.vIEw.PagerAdapter;import androID.vIEw.Gravity;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.Widget.TextVIEw;public class MainActivity extends Activity { @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); LoopVIEwPager vIEwpager = (LoopVIEwPager) findVIEwByID(R.ID.vIEwpager); vIEwpager.setAdapter(new SamplePagerAdapter()); } public class SamplePagerAdapter extends PagerAdapter { private final Random random = new Random(); private int mSize; public SamplePagerAdapter() {  mSize = 5; } public SamplePagerAdapter(int count) {  mSize = count; } @OverrIDe public int getCount() {  return mSize; } @OverrIDe public boolean isVIEwFromObject(VIEw vIEw,Object object) {  return vIEw == object; } @OverrIDe public voID destroyItem(VIEwGroup vIEw,int position,Object object) {  vIEw.removeVIEw((VIEw) object); } @OverrIDe public Object instantiateItem(VIEwGroup vIEw,int position) {  TextVIEw textVIEw = new TextVIEw(vIEw.getContext());  textVIEw.setText(position + 1 + "");  textVIEw.setBackgroundcolor(0xff000000 | random.nextInt(0x00ffffff));  textVIEw.setGravity(Gravity.CENTER);  textVIEw.setTextcolor(color.WHITE);  textVIEw.setTextSize(50);  vIEw.addVIEw(textVIEw,VIEwGroup.LayoutParams.MATCH_PARENT,VIEwGroup.LayoutParams.MATCH_PARENT);  return textVIEw; } // 增加item public voID addItem() {  mSize++;  notifyDataSetChanged(); } // 删除item public voID removeItem() {  mSize--;  mSize = mSize < 0 ? 0 : mSize;  notifyDataSetChanged(); } }}

MainActivity.java需要的布局文件activity_main.xml:

<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="zhangphil.demo.MainActivity" >  <zhangphil.demo.LoopVIEwPager    androID:ID="@+ID/vIEwpager"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"/></relativeLayout> 

核心关键代码LoopVIEwPager.java类和LoopVIEwPager.java依赖的LoopPagerAdapterWrapper.java! 

LoopVIEwPager.java: 

package zhangphil.demo;import androID.content.Context;import androID.support.v4.vIEw.PagerAdapter;import androID.support.v4.vIEw.VIEwPager;import androID.util.AttributeSet;import java.util.ArrayList;import java.util.List;public class LoopVIEwPager extends VIEwPager { private static final boolean DEFAulT_BOUNDARY_CASHING = false; private static final boolean DEFAulT_BOUNDARY_LOOPing = true; private LoopPagerAdapterWrapper mAdapter; private boolean mBoundaryCaching = DEFAulT_BOUNDARY_CASHING; private boolean mBoundaryLooPing = DEFAulT_BOUNDARY_LOOPing; private List<OnPagechangelistener> mOnPagechangelisteners; /** * helper function which may be used when implementing FragmentPagerAdapter * * @return (position-1)%count */ public static int toRealposition(int position,int count) { position = position - 1; if (position < 0) {  position += count; } else {  position = position % count; } return position; } /** * If set to true,the boundary vIEws (i.e. first and last) will never be * destroyed This may help to prevent "blinking" of some vIEws */ public voID setBoundaryCaching(boolean flag) { mBoundaryCaching = flag; if (mAdapter != null) {  mAdapter.setBoundaryCaching(flag); } } public voID setBoundaryLooPing(boolean flag) { mBoundaryLooPing = flag; if (mAdapter != null) {  mAdapter.setBoundaryLooPing(flag); } } @OverrIDe public voID setAdapter(PagerAdapter adapter) { mAdapter = new LoopPagerAdapterWrapper(adapter); mAdapter.setBoundaryCaching(mBoundaryCaching); mAdapter.setBoundaryLooPing(mBoundaryLooPing); super.setAdapter(mAdapter); setCurrentItem(0,false); } @OverrIDe public PagerAdapter getAdapter() { return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter; } @OverrIDe public int getCurrentItem() { return mAdapter != null ? mAdapter.toRealposition(super.getCurrentItem()) : 0; } public voID setCurrentItem(int item,boolean smoothScroll) { int realitem = mAdapter.toInnerposition(item); super.setCurrentItem(realitem,smoothScroll); } @OverrIDe public voID setCurrentItem(int item) { if (getCurrentItem() != item) {  setCurrentItem(item,true); } } @OverrIDe public voID setonPagechangelistener(OnPagechangelistener Listener) { addOnPagechangelistener(Listener); } @OverrIDe public voID addOnPagechangelistener(OnPagechangelistener Listener) { if (mOnPagechangelisteners == null) {  mOnPagechangelisteners = new ArrayList<>(); } mOnPagechangelisteners.add(Listener); } @OverrIDe public voID removeOnPagechangelistener(OnPagechangelistener Listener) { if (mOnPagechangelisteners != null) {  mOnPagechangelisteners.remove(Listener); } } @OverrIDe public voID clearOnPagechangelisteners() { if (mOnPagechangelisteners != null) {  mOnPagechangelisteners.clear(); } } public LoopVIEwPager(Context context) { super(context); init(context); } public LoopVIEwPager(Context context,AttributeSet attrs) { super(context,attrs); init(context); } private voID init(Context context) { if (onPagechangelistener != null) {  super.removeOnPagechangelistener(onPagechangelistener); } super.addOnPagechangelistener(onPagechangelistener); } private OnPagechangelistener onPagechangelistener = new OnPagechangelistener() { private float mPrevIoUsOffset = -1; private float mPrevIoUsposition = -1; @OverrIDe public voID onPageSelected(int position) {  int realposition = mAdapter.toRealposition(position);  if (mPrevIoUsposition != realposition) {  mPrevIoUsposition = realposition;  if (mOnPagechangelisteners != null) {   for (int i = 0; i < mOnPagechangelisteners.size(); i++) {   OnPagechangelistener Listener = mOnPagechangelisteners.get(i);   if (Listener != null) {    Listener.onPageSelected(realposition);   }   }  }  } } @OverrIDe public voID onPageScrolled(int position,float positionOffset,int positionOffsetPixels) {  int realposition = position;  if (mAdapter != null) {  realposition = mAdapter.toRealposition(position);  if (positionOffset == 0 && mPrevIoUsOffset == 0   && (position == 0 || position == mAdapter.getCount() - 1)) {   setCurrentItem(realposition,false);  }  }  mPrevIoUsOffset = positionOffset;  if (mOnPagechangelisteners != null) {  for (int i = 0; i < mOnPagechangelisteners.size(); i++) {   OnPagechangelistener Listener = mOnPagechangelisteners.get(i);   if (Listener != null) {   if (realposition != mAdapter.getRealCount() - 1) {    Listener.onPageScrolled(realposition,positionOffset,positionOffsetPixels);   } else {    if (positionOffset > .5) {    Listener.onPageScrolled(0,0);    } else {    Listener.onPageScrolled(realposition,0);    }   }   }  }  } } @OverrIDe public voID onPageScrollStateChanged(int state) {  if (mAdapter != null) {  int position = LoopVIEwPager.super.getCurrentItem();  int realposition = mAdapter.toRealposition(position);  if (state == VIEwPager.SCRolL_STATE_IDLE && (position == 0 || position == mAdapter.getCount() - 1)) {   setCurrentItem(realposition,false);  }  }  if (mOnPagechangelisteners != null) {  for (int i = 0; i < mOnPagechangelisteners.size(); i++) {   OnPagechangelistener Listener = mOnPagechangelisteners.get(i);   if (Listener != null) {   Listener.onPageScrollStateChanged(state);   }  }  } } };}

LoopPagerAdapterWrapper.java:

package zhangphil.demo;import androID.os.Parcelable;import androID.support.v4.app.FragmentPagerAdapter;import androID.support.v4.app.FragmentStatePagerAdapter;import androID.support.v4.vIEw.PagerAdapter;import androID.util.SparseArray;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;public class LoopPagerAdapterWrapper extends PagerAdapter { private PagerAdapter mAdapter; private SparseArray<ToDestroy> mToDestroy = new SparseArray<>(); private static final boolean DEFAulT_BOUNDARY_CASHING = true; private static final boolean DEFAulT_BOUNDARY_LOOPing = true; private boolean mBoundaryCaching = DEFAulT_BOUNDARY_CASHING; private boolean mBoundaryLooPing = DEFAulT_BOUNDARY_LOOPing; voID setBoundaryCaching(boolean flag) { mBoundaryCaching = flag; } voID setBoundaryLooPing(boolean flag) { mBoundaryLooPing = flag; } LoopPagerAdapterWrapper(PagerAdapter adapter) { this.mAdapter = adapter; } @OverrIDe public voID notifyDataSetChanged() { mToDestroy = new SparseArray<>(); super.notifyDataSetChanged(); } int toRealposition(int position) { int realposition = position; int realCount = getRealCount(); if (realCount == 0)  return 0; if (mBoundaryLooPing) {  realposition = (position - 1) % realCount;  if (realposition < 0)  realposition += realCount; } return realposition; } public int toInnerposition(int realposition) { int position = (realposition + 1); return mBoundaryLooPing ? position : realposition; } private int getRealFirstposition() { return mBoundaryLooPing ? 1 : 0; } private int getRealLastposition() { return getRealFirstposition() + getRealCount() - 1; } @OverrIDe public int getCount() { int count = getRealCount(); return mBoundaryLooPing ? count + 2 : count; } public int getRealCount() { return mAdapter.getCount(); } public PagerAdapter getRealAdapter() { return mAdapter; } @OverrIDe public Object instantiateItem(VIEwGroup container,int position) { int realposition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)  ? position : toRealposition(position); if (mBoundaryCaching) {  ToDestroy toDestroy = mToDestroy.get(position);  if (toDestroy != null) {  mToDestroy.remove(position);  return toDestroy.object;  } } return mAdapter.instantiateItem(container,realposition); } @OverrIDe public voID destroyItem(VIEwGroup container,Object object) { int realFirst = getRealFirstposition(); int realLast = getRealLastposition(); int realposition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)  ? position : toRealposition(position); if (mBoundaryCaching && (position == realFirst || position == realLast)) {  mToDestroy.put(position,new ToDestroy(container,realposition,object)); } else {  mAdapter.destroyItem(container,object); } } /* * Delegate rest of methods directly to the inner adapter. */ @OverrIDe public voID finishUpdate(VIEwGroup container) { mAdapter.finishUpdate(container); } @OverrIDe public boolean isVIEwFromObject(VIEw vIEw,Object object) { return mAdapter.isVIEwFromObject(vIEw,object); } @OverrIDe public voID restoreState(Parcelable bundle,ClassLoader classLoader) { mAdapter.restoreState(bundle,classLoader); } @OverrIDe public Parcelable saveState() { return mAdapter.saveState(); } @OverrIDe public voID startUpdate(VIEwGroup container) { mAdapter.startUpdate(container); } @OverrIDe public voID setPrimaryItem(VIEwGroup container,Object object) { mAdapter.setPrimaryItem(container,position,object); } /* * End delegation */ /** * Container class for caching the boundary vIEws */ static class ToDestroy { VIEwGroup container; int position; Object object; public ToDestroy(VIEwGroup container,Object object) {  this.container = container;  this.position = position;  this.object = object; } }}

如果读者有兴趣使用,直接将上面两个核心关键代码放入到自己的项目代码包中,当作自己写的类直接使用即可,写布局时候不要再写VIEwPager,而是直接像我上面写的那个布局文件一样用LoopVIEwPager。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android ViewPager实现智能无限循环滚动回绕效果全部内容,希望文章能够帮你解决Android ViewPager实现智能无限循环滚动回绕效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1145623.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存