android自动循环筛选,Android实现带指示点的自动轮播无限循环效果

想要实现无限轮播,一直向左滑动,当到最后一个view时,会滑动到第一个,无限…

可以自己写ViewPager然后加handler先实现自动滚动,当然这里我为了项目的进度直接使用了Trinea的Android-auto-scroll-view-pager库,网址:点击进入github 引用库compile('cn.trinea.android.view.autoscrollviewpager:android-auto-scroll-view-pager:1.1.2') {

exclude module: 'support-v4'之后

1布局为

android:layout_width="match_parent"

android:layout_height="@dimen/y150">

android:id="@+id/viewpager1"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/ll_dot1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_marginBottom="8dp"

android:gravity="center"

android:orientation="horizontal" />

2 构建PagerAdapter

继承自RecyclingPagerAdapter (后面会贴出来源码)

`public class Indicator1Adapter extends RecyclingPagerAdapter {

private List imageIdList;

Context context;

//是否循环(创造构造方法,在activity里设置是否)

//集合大小

private int size;

public Indicator1Adapter(List mData, Context context) {

this.imageIdList = mData;

this.context = context;

this.size = mData.size();

isInfiniteLoop = false;

}

@Override

public int getCount() {

//是:最大(让集合的长度无限,从而模拟无限循环) 否,集合长度

return isInfiniteLoop ? Integer.MAX_VALUE : imageIdList.size();

}

/**

* @return the isInfiniteLoop

*/

public boolean isInfiniteLoop() {

return isInfiniteLoop;

}

/**

* @param是否无限循环

*/

public Indicator1Adapter setInfiniteLoop(boolean isInfiniteLoop) {

this.isInfiniteLoop = isInfiniteLoop;

return this;

}

/**

* 真实的position

*

* @param position

* @return

*/

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);

view.setTag(holder);

} else {

holder = (ViewHolder)view.getTag();

}

holder.imageView.setImageResource(imageIdList.get(getPosition(position)));

holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY);

return view;

}

private static class ViewHolder {

ImageView imageView;

}

}

3 在activity里或者fragment里就可以设置ViewPager

定义的成员变量:

//viewpager1

@BindView(R.id.viewpager1)

AutoScrollViewPager mPager1;

//承载小点点的控件容器(布局里有)

@BindView(R.id.ll_dot1)

LinearLayout mLlDot1;

Indicator1Adapter adapter1 = new Indicator1Adapter( mData,act).setInfiniteLoop(true);//开启无限循环

mPager1.setAdapter(adapter1);

mPager1.setInterval(PLAY_TIME);//轮播时间间隔

mPager1.startAutoScroll();//开启自动轮播

mPager1.setCurrentItem(Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mData.size());

然后你嫌弃官方的换图间隔时间太短,一闪而过,可以通过反射 设置

//通过反射让滚动速度为自己的喜好的(这里设为1.2s)

try {

Field field = ViewPager.class.getDeclaredField("mScroller");

field.setAccessible(true);

FixedSpeedScroller scroller = new FixedSpeedScroller(mPager1.getContext(),

new AccelerateInterpolator());

field.set(mPager1, scroller);

scroller.setmDuration(1200);

} catch (Exception e) {

Log.e(TAG, "Exception", e);

}

4 然后我们的小点点还没有使用呢

这里我写了方法:

/**

* 设置状态点1

*/

private void setOvalLayout1() {

for (int i = 0; i < mData.size(); i++) {

/**

* 生成对应数量的点点(布局,结果提供)

*/

mLlDot1.addView(inflater.inflate(R.layout.dot, null));

}

// 默认显示第一页

mLlDot1.getChildAt(0).findViewById(R.id.v_dot)

.setBackgroundResource(R.drawable.dot_selected);

mPager1.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

public void onPageSelected(int position) {

//遍历图片数组

// Toast.makeText(act, "position"+position, Toast.LENGTH_SHORT).show();

for (int i = 0; i < mData.size(); i++) {

if(i==position%mData.size()){

// 圆点选中

/**

* 这里需要注意如果直接写position,由于我们是无限循环,他的position是无限往上

*增加的,那么就会报空指针,因为我们总共才生成了mData.size()个点点,这里可以让当前的

*position取余,得到的即是当前位置的点点

*/

mLlDot1.getChildAt(position%mData.size())

.findViewById(R.id.v_dot)

.setBackgroundResource(R.drawable.dot_selected);

}else{

// 取消圆点选中

mLlDot1.getChildAt(curIndex1%mData.size())

.findViewById(R.id.v_dot)

.setBackgroundResource(R.drawable.dot_normal);

}

}

curIndex1 = position;

}

public void onPageScrolled(int arg0, float arg1, int arg2) {

}

public void onPageScrollStateChanged(int arg0) {

}

});

}

别忘了重写

@Override

public void onPause() {

super.onPause();

// stop auto scroll when onPause

mPager1.stopAutoScroll();

}

@Override

public void onResume() {

super.onResume();

// start auto scroll when onResume

mPager1.startAutoScroll();

}

好了,无限循环自动轮播,完成了.

5点点布局:

android:layout_width="wrap_content"

android:layout_height="wrap_content">

android:id="@+id/v_dot"

android:layout_width="8dp"

android:layout_height="8dp"

android:layout_marginLeft="2dp"

android:layout_marginRight="2dp"

android:background="@drawable/dot_normal"/>

6 点点的background

dot_normal.xml

android:shape="oval">

dot_selected.xml

android:shape="oval">

RecyclingPagerAdapter的源码依赖RecycleBin类,一并贴出来

public class RecycleBin {

/**

* Views that were on screen at the start of layout. This array is populated at the start of

* layout, and at the end of layout all view in activeViews are moved to scrapViews.

* Views in activeViews represent a contiguous range of Views, with position of the first

* view store in mFirstActivePosition.

*/

private View[] activeViews = new View[0];

private int[] activeViewTypes = new int[0];

/** Unsorted views that can be used by the adapter as a convert view. */

private SparseArray[] scrapViews;

private int viewTypeCount;

private SparseArray currentScrapViews;

public void setViewTypeCount(int viewTypeCount) {

if (viewTypeCount < 1) {

throw new IllegalArgumentException("Can't have a viewTypeCount < 1");

}

//noinspection unchecked

SparseArray[] scrapViews = new SparseArray[viewTypeCount];

for (int i = 0; i < viewTypeCount; i++) {

scrapViews[i] = new SparseArray();

}

this.viewTypeCount = viewTypeCount;

currentScrapViews = scrapViews[0];

this.scrapViews = scrapViews;

}

protected boolean shouldRecycleViewType(int viewType) {

return viewType >= 0;

}

/** @return A view from the ScrapViews collection. These are unordered. */

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;

}

/**

* Put a view into the ScrapViews list. These views are unordered.

*

* @param scrap The view to add

*/

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);

}

}

/** Move all views remaining in activeViews to scrapViews. */

void scrapActiveViews() {

final View[] activeViews = this.activeViews;

final int[] activeViewTypes = this.activeViewTypes;

final boolean multipleScraps = viewTypeCount > 1;

SparseArray 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();

}

/**

* Makes sure that the size of scrapViews does not exceed the size of activeViews.

* (This can happen if an adapter does not recycle its views).

*/

private void pruneScrapViews() {

final int maxViews = activeViews.length;

final int viewTypeCount = this.viewTypeCount;

final SparseArray[] scrapViews = this.scrapViews;

for (int i = 0; i < viewTypeCount; ++i) {

final SparseArray 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 scrapViews, int position) {

int size = scrapViews.size();

if (size > 0) {

// See if we still have a view for this position.

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;

}

}

}

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;

}

/**

*

* Returns the number of types of Views that will be created by

* {@link #getView}. Each type represents a set of views that can be

* converted in {@link #getView}. If the adapter always returns the same

* type of View for all items, this method should return 1.

*

*

* This method will only be called when when the adapter is set on the

* the {@link AdapterView}.

*

*

* @return The number of types of Views that will be created by this adapter

*/

public int getViewTypeCount() {

return 1;

}

/**

* Get the type of View that will be created by {@link #getView} for the specified item.

*

* @param position The position of the item within the adapter's data set whose view type we

* want.

* @return An integer representing the type of View. Two views should share the same type if one

* can be converted to the other in {@link #getView}. Note: Integers must be in the

* range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can

* also be returned.

* @see #IGNORE_ITEM_VIEW_TYPE

*/

@SuppressWarnings("UnusedParameters") // Argument potentially used by subclasses.

public int getItemViewType(int position) {

return 0;

}

/**

* Get a View that displays the data at the specified position in the data set. You can either

* create a View manually or inflate it from an XML layout file. When the View is inflated, the

* parent View (GridView, ListView...) will apply default layout parameters unless you use

* {@link android.view.LayoutInflater#inflate(int, ViewGroup, boolean)}

* to specify a root view and to prevent attachment to the root.

*

* @param position The position of the item within the adapter's data set of the item whose view

* we want.

* @param convertView The old view to reuse, if possible. Note: You should check that this view

* is non-null and of an appropriate type before using. If it is not possible to convert

* this view to display the correct data, this method can create a new view.

* Heterogeneous lists can specify their number of view types, so that this View is

* always of the right type (see {@link #getViewTypeCount()} and

* {@link #getItemViewType(int)}).

* @return A View corresponding to the data at the specified position.

*/

public abstract View getView(int position, View convertView, ViewGroup container);

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值