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'){
excludemodule:'support-v4'之后
1布局为
<RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/y150"> <cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager android:id="@+id/viewpager1" android:layout_width="match_parent" android:layout_height="wrap_content"/> <!--点点的布局--> <LinearLayout 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"/> </RelativeLayout>
2构建PagerAdapter
继承自RecyclingPagerAdapter(后面会贴出来源码)
`publicclassIndicator1AdapterextendsRecyclingPagerAdapter{
privateList<Integer>imageIdList;
Contextcontext;
//是否循环(创造构造方法,在activity里设置是否)
//集合大小
privateintsize;
publicIndicator1Adapter(List<Integer>mData,Contextcontext){
this.imageIdList=mData;
this.context=context;
this.size=mData.size();
isInfiniteLoop=false;
}
@Override
publicintgetCount(){
//是:最大(让集合的长度无限,从而模拟无限循环)否,集合长度
returnisInfiniteLoop?Integer.MAX_VALUE:imageIdList.size();
}
/**
*@returntheisInfiniteLoop
*/
publicbooleanisInfiniteLoop(){
returnisInfiniteLoop;
}
/**
*@param是否无限循环
*/
publicIndicator1AdaptersetInfiniteLoop(booleanisInfiniteLoop){
this.isInfiniteLoop=isInfiniteLoop;
returnthis;
}
/**
*真实的position
*
*@paramposition
*@return
*/
privateintgetPosition(intposition){
returnisInfiniteLoop?position%size:position;
}
@Override
publicViewgetView(intposition,Viewview,ViewGroupcontainer){
ViewHolderholder;
if(view==null){
holder=newViewHolder();
view=holder.imageView=newImageView(context);
view.setTag(holder);
}else{
holder=(ViewHolder)view.getTag();
}
holder.imageView.setImageResource(imageIdList.get(getPosition(position)));
holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY);
returnview;
}
privatestaticclassViewHolder{
ImageViewimageView;
}
}
3在activity里或者fragment里就可以设置ViewPager
定义的成员变量:
//viewpager1 @BindView(R.id.viewpager1) AutoScrollViewPagermPager1; //承载小点点的控件容器(布局里有) @BindView(R.id.ll_dot1) LinearLayoutmLlDot1;
Indicator1Adapteradapter1=newIndicator1Adapter(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{
Fieldfield=ViewPager.class.getDeclaredField("mScroller");
field.setAccessible(true);
FixedSpeedScrollerscroller=newFixedSpeedScroller(mPager1.getContext(),
newAccelerateInterpolator());
field.set(mPager1,scroller);
scroller.setmDuration(1200);
}catch(Exceptione){
Log.e(TAG,"Exception",e);
}
4然后我们的小点点还没有使用呢
这里我写了方法:
/**
*设置状态点1
*/
privatevoidsetOvalLayout1(){
for(inti=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(newViewPager.OnPageChangeListener(){
publicvoidonPageSelected(intposition){
//遍历图片数组
//Toast.makeText(act,"position"+position,Toast.LENGTH_SHORT).show();
for(inti=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;
}
publicvoidonPageScrolled(intarg0,floatarg1,intarg2){
}
publicvoidonPageScrollStateChanged(intarg0){
}
});
}
别忘了重写
@Override
publicvoidonPause(){
super.onPause();
//stopautoscrollwhenonPause
mPager1.stopAutoScroll();
}
@Override
publicvoidonResume(){
super.onResume();
//startautoscrollwhenonResume
mPager1.startAutoScroll();
}
好了,无限循环自动轮播,完成了.
5点点布局:
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <!--小圆点View--> <View 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"/> </RelativeLayout>
6点点的background
dot_normal.xml
<?xmlversion="1.0"encoding="utf-8"?><!--圆点未选中--> <shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solidandroid:color="@color/background_color"/> <cornersandroid:radius="5dp"/> </shape>
dot_selected.xml
<?xmlversion="1.0"encoding="utf-8"?><!--圆点选中--> <shapexmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solidandroid:color="@color/red"/> <cornersandroid:radius="5dp"/> </shape>
RecyclingPagerAdapter的源码依赖RecycleBin类,一并贴出来
publicclassRecycleBin{
/**
*Viewsthatwereonscreenatthestartoflayout.Thisarrayispopulatedatthestartof
*layout,andattheendoflayoutallviewinactiveViewsaremovedtoscrapViews.
*ViewsinactiveViewsrepresentacontiguousrangeofViews,withpositionofthefirst
*viewstoreinmFirstActivePosition.
*/
privateView[]activeViews=newView[0];
privateint[]activeViewTypes=newint[0];
/**Unsortedviewsthatcanbeusedbytheadapterasaconvertview.*/
privateSparseArray<View>[]scrapViews;
privateintviewTypeCount;
privateSparseArray<View>currentScrapViews;
publicvoidsetViewTypeCount(intviewTypeCount){
if(viewTypeCount<1){
thrownewIllegalArgumentException("Can'thaveaviewTypeCount<1");
}
//noinspectionunchecked
SparseArray<View>[]scrapViews=newSparseArray[viewTypeCount];
for(inti=0;i<viewTypeCount;i++){
scrapViews[i]=newSparseArray<View>();
}
this.viewTypeCount=viewTypeCount;
currentScrapViews=scrapViews[0];
this.scrapViews=scrapViews;
}
protectedbooleanshouldRecycleViewType(intviewType){
returnviewType>=0;
}
/**@returnAviewfromtheScrapViewscollection.Theseareunordered.*/
ViewgetScrapView(intposition,intviewType){
if(viewTypeCount==1){
returnretrieveFromScrap(currentScrapViews,position);
}elseif(viewType>=0&&viewType<scrapViews.length){
returnretrieveFromScrap(scrapViews[viewType],position);
}
returnnull;
}
/**
*PutaviewintotheScrapViewslist.Theseviewsareunordered.
*
*@paramscrapTheviewtoadd
*/
voidaddScrapView(Viewscrap,intposition,intviewType){
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);
}
}
/**MoveallviewsremaininginactiveViewstoscrapViews.*/
voidscrapActiveViews(){
finalView[]activeViews=this.activeViews;
finalint[]activeViewTypes=this.activeViewTypes;
finalbooleanmultipleScraps=viewTypeCount>1;
SparseArray<View>scrapViews=currentScrapViews;
finalintcount=activeViews.length;
for(inti=count-1;i>=0;i--){
finalViewvictim=activeViews[i];
if(victim!=null){
intwhichScrap=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();
}
/**
*MakessurethatthesizeofscrapViewsdoesnotexceedthesizeofactiveViews.
*(Thiscanhappenifanadapterdoesnotrecycleitsviews).
*/
privatevoidpruneScrapViews(){
finalintmaxViews=activeViews.length;
finalintviewTypeCount=this.viewTypeCount;
finalSparseArray<View>[]scrapViews=this.scrapViews;
for(inti=0;i<viewTypeCount;++i){
finalSparseArray<View>scrapPile=scrapViews[i];
intsize=scrapPile.size();
finalintextras=size-maxViews;
size--;
for(intj=0;j<extras;j++){
scrapPile.remove(scrapPile.keyAt(size--));
}
}
}
staticViewretrieveFromScrap(SparseArray<View>scrapViews,intposition){
intsize=scrapViews.size();
if(size>0){
//Seeifwestillhaveaviewforthisposition.
for(inti=0;i<size;i++){
intfromPosition=scrapViews.keyAt(i);
Viewview=scrapViews.get(fromPosition);
if(fromPosition==position){
scrapViews.remove(fromPosition);
returnview;
}
}
intindex=size-1;
Viewr=scrapViews.valueAt(index);
scrapViews.remove(scrapViews.keyAt(index));
returnr;
}else{
returnnull;
}
}
}
RecyclingPagerAdapter
publicabstractclassRecyclingPagerAdapterextendsPagerAdapter{
staticfinalintIGNORE_ITEM_VIEW_TYPE=AdapterView.ITEM_VIEW_TYPE_IGNORE;
privatefinalRecycleBinrecycleBin;
publicRecyclingPagerAdapter(){
this(newRecycleBin());
}
RecyclingPagerAdapter(RecycleBinrecycleBin){
this.recycleBin=recycleBin;
recycleBin.setViewTypeCount(getViewTypeCount());
}
@OverridepublicvoidnotifyDataSetChanged(){
recycleBin.scrapActiveViews();
super.notifyDataSetChanged();
}
@OverridepublicfinalObjectinstantiateItem(ViewGroupcontainer,intposition){
intviewType=getItemViewType(position);
Viewview=null;
if(viewType!=IGNORE_ITEM_VIEW_TYPE){
view=recycleBin.getScrapView(position,viewType);
}
view=getView(position,view,container);
container.addView(view);
returnview;
}
@OverridepublicfinalvoiddestroyItem(ViewGroupcontainer,intposition,Objectobject){
Viewview=(View)object;
container.removeView(view);
intviewType=getItemViewType(position);
if(viewType!=IGNORE_ITEM_VIEW_TYPE){
recycleBin.addScrapView(view,position,viewType);
}
}
@OverridepublicfinalbooleanisViewFromObject(Viewview,Objectobject){
returnview==object;
}
/**
*<p>
*ReturnsthenumberoftypesofViewsthatwillbecreatedby
*{@link#getView}.Eachtyperepresentsasetofviewsthatcanbe
*convertedin{@link#getView}.Iftheadapteralwaysreturnsthesame
*typeofViewforallitems,thismethodshouldreturn1.
*</p>
*<p>
*Thismethodwillonlybecalledwhenwhentheadapterissetonthe
*the{@linkAdapterView}.
*</p>
*
*@returnThenumberoftypesofViewsthatwillbecreatedbythisadapter
*/
publicintgetViewTypeCount(){
return1;
}
/**
*GetthetypeofViewthatwillbecreatedby{@link#getView}forthespecifieditem.
*
*@parampositionThepositionoftheitemwithintheadapter'sdatasetwhoseviewtypewe
*want.
*@returnAnintegerrepresentingthetypeofView.Twoviewsshouldsharethesametypeifone
*canbeconvertedtotheotherin{@link#getView}.Note:Integersmustbeinthe
*range0to{@link#getViewTypeCount}-1.{@link#IGNORE_ITEM_VIEW_TYPE}can
*alsobereturned.
*@see#IGNORE_ITEM_VIEW_TYPE
*/
@SuppressWarnings("UnusedParameters")//Argumentpotentiallyusedbysubclasses.
publicintgetItemViewType(intposition){
return0;
}
/**
*GetaViewthatdisplaysthedataatthespecifiedpositioninthedataset.Youcaneither
*createaViewmanuallyorinflateitfromanXMLlayoutfile.WhentheViewisinflated,the
*parentView(GridView,ListView...)willapplydefaultlayoutparametersunlessyouuse
*{@linkandroid.view.LayoutInflater#inflate(int,ViewGroup,boolean)}
*tospecifyarootviewandtopreventattachmenttotheroot.
*
*@parampositionThepositionoftheitemwithintheadapter'sdatasetoftheitemwhoseview
*wewant.
*@paramconvertViewTheoldviewtoreuse,ifpossible.Note:Youshouldcheckthatthisview
*isnon-nullandofanappropriatetypebeforeusing.Ifitisnotpossibletoconvert
*thisviewtodisplaythecorrectdata,thismethodcancreateanewview.
*Heterogeneouslistscanspecifytheirnumberofviewtypes,sothatthisViewis
*alwaysoftherighttype(see{@link#getViewTypeCount()}and
*{@link#getItemViewType(int)}).
*@returnAViewcorrespondingtothedataatthespecifiedposition.
*/
publicabstractViewgetView(intposition,ViewconvertView,ViewGroupcontainer);
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。