Android Studio - 第四十六期 不会ANR的轮播写法
最近在学习撸撸的代码,发现他的轮播写法很独特,但是有bug,就重新修改了一下,现在支持左右点击和圆点自定义。 BannerAdapter:(注意适配器自己看ImageView和onclick的自己项目的写法~) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 package com.example.p029_banner_lunbo.adapter; import android.app.Activity; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.example.p029_banner_lunbo.bannerutils.BannerView; import com.example.p029_banner_lunbo.domain.Biaoge_listBean; import java.util.List; public class BannerAdapter extends BannerView.Adapter{ private List<Biaoge_listBean>mAdList; private ObjectmReceiver; public BannerAdapter(Objectreceiver,List<Biaoge_listBean>items){ mReceiver=receiver; mAdList=items; } @Override public int getRealCount(){ return mAdList.size(); } @Override public ObjectinstantiateItem( final ViewGroupcontainer, int position){ int size=mAdList.size(); if (size== 0 ){ return null ; } final int pos=position%size; final Biaoge_listBeanitem=mAdList.get(pos); ViewGroup.LayoutParamsp= new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); ImageViewiv= new ImageView(container.getContext()); iv.setScaleType(ImageView.ScaleType.FIT_XY); iv.setAdjustViewBounds( true ); container.addView(iv,p); iv.setBackgroundResource(item.getImg_url()); //GlideUtil.display(container.getContext(),iv,item.getPic_url(), //GlideOptionsFactory.get(GlideOptionsFactory.Type.RADIUS)); iv.setOnClickListener( new View.OnClickListener(){ @Override public void onClick(Viewv){ //MobEventHelper.onEvent(container.getContext(),"UI2_ec_index_banner"); //MobEventHelper.onEvent(container.getContext(),"UI2_ec_index_banner_"+String.valueOf(pos+1)); if (container.getContext() instanceof Activity){ Activityact=(Activity)container.getContext(); //跳转bufen //HiosHelper.resolveAd(act,mReceiver,item.getUrl()); } } }); return iv; } @Override public void destroyItem(ViewGroupcontainer, int position,Objectobject){ container.removeView((View)object); } } DotIndicatorView:(圆点的方法大部分都public了,大家可以DotIndicatorView.自定义~) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 package com.example.p029_banner_lunbo.bannerutils; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; /** *圆点导航 *@authorgeek * */ public class DotIndicatorView extends View{ private PaintmPaint; private int mPadding; private int mCircleRadius; private int mCurrentColor; private int mNormalColor; private int mCount= 3 ; private int mCurrent; public DotIndicatorView(Contextcontext){ super (context); initView(); } public DotIndicatorView(Contextcontext,AttributeSetattrs){ this (context,attrs, 0 ); } public DotIndicatorView(Contextcontext,AttributeSetattrs, int defStyle){ super (context,attrs,defStyle); initView(); } private void initView(){ DisplayMetricsdm=getResources().getDisplayMetrics(); mPadding=( int )TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10 ,dm); mCircleRadius=( int )TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4 ,dm); mCurrentColor=Color.WHITE; mNormalColor=Color.argb( 88 , 91 , 91 , 91 ); mPaint= new Paint(Paint.ANTI_ALIAS_FLAG); } @Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec){ int width=mCircleRadius* 2 *mCount+mPadding*(mCount- 1 ); int height=mCircleRadius* 2 ; setMeasuredDimension(width,height); } @Override protected void onDraw(Canvascanvas){ for ( int i= 0 ;i<mCount;i++){ canvas.save(); canvas.translate((mCircleRadius* 2 +mPadding)*i, 0 ); if (i==mCurrent)mPaint.setColor(mCurrentColor); else mPaint.setColor(mNormalColor); canvas.drawCircle(mCircleRadius,mCircleRadius,mCircleRadius,mPaint); canvas.restore(); } } /** *创建导航 *@paramcount个数 */ public void create( int count){ mCount=count; requestLayout(); invalidate(); } /** *选中当前 *@paramposition选中位置 */ public void current( int position){ mCurrent=position; invalidate(); } /** *获取当前选中的位置 *@return */ public int current(){ return mCurrent; } } BannerView:(自定义的View~) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 package com.example.p029_banner_lunbo.bannerutils; import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Parcelable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import com.example.p029_banner_lunbo.R; import java.lang.ref.WeakReference; public class BannerView extends FrameLayout{ private static final int MSG_RUN= 1 ; private ViewPagermViewPager; /** *导航的小点 */ private DotIndicatorViewmIndicator; private AdaptermAdapter; /** *是否处于滑动的状态 */ private boolean isScrolling; private int mIndicatorPosition; //center_horileft /** *是否显示indicator */ private boolean isShowIndicator= true ; private boolean isTouch; private HandlermHandler; private BannerViewHelpermHelper; private int mScrollTime; public BannerView(Contextcontext,AttributeSetattrs){ this (context,attrs, 0 ); } public BannerView(Contextcontext,AttributeSetattrs, int defStyle){ super (context,attrs,defStyle); TypedArrayta=context.obtainStyledAttributes(attrs,R.styleable.BannerView, defStyle, 0 ); mIndicatorPosition=ta.getInt(R.styleable.BannerView_indicator_position, 0 ); isShowIndicator=ta.getBoolean(R.styleable.BannerView_indicator_visible, true ); mScrollTime=ta.getInteger(R.styleable.BannerView_scroll_time, 3000 ); isScrolling=ta.getBoolean(R.styleable.BannerView_auto_start, false ); ta.recycle(); initView(context); } private void initView(Contextcontext){ mViewPager= new ViewPager(context); mViewPager.addOnPageChangeListener(mOnPageChangeListener); addView(mViewPager); //,viewPagerParams); mHandler= new H(mViewPager); mIndicator= new DotIndicatorView(context); LayoutParamsindicatorParams= new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); if (mIndicatorPosition== 0 ){ indicatorParams.gravity=Gravity.BOTTOM|Gravity.LEFT; } else if (mIndicatorPosition== 1 ){ indicatorParams.gravity=Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL; } else if (mIndicatorPosition== 2 ){ indicatorParams.gravity=Gravity.BOTTOM|Gravity.RIGHT; } indicatorParams.bottomMargin= 20 ; if (!isShowIndicator){ return ; } addView(mIndicator,indicatorParams); } @Override protected void onAttachedToWindow(){ if (isScrolling){ startScroll(); } super .onAttachedToWindow(); mHelper= new BannerViewHelper( this ); } @Override public boolean dispatchTouchEvent(MotionEventev){ if (mHelper!= null ){ mHelper.resolveTouchConflict(ev); } return super .dispatchTouchEvent(ev); } @Override protected LayoutParamsgenerateDefaultLayoutParams(){ return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } @Override public LayoutParamsgenerateLayoutParams(AttributeSetattrs){ return new LayoutParams(getContext(),attrs); } @Override protected android.view.ViewGroup.LayoutParamsgenerateLayoutParams( android.view.ViewGroup.LayoutParamsp){ return new LayoutParams(p); } @Override protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParamsp){ return p instanceof LayoutParams; } private OnPageChangeListenermOnPageChangeListener= new OnPageChangeListener(){ @Override public void onPageSelected( int position){ int relCount=mAdapter.getRealCount(); if (relCount<= 0 ){ mIndicator.current( 0 ); } else { mIndicator.current(position%relCount); } } @Override public void onPageScrolled( int arg0, float arg1, int arg2){ } @Override public void onPageScrollStateChanged( int arg0){ isTouch=arg0==ViewPager.SCROLL_STATE_DRAGGING; if (arg0==ViewPager.SCROLL_STATE_IDLE&&isScrolling){ mHandler.removeMessages(MSG_RUN); Messagemsg=mHandler.obtainMessage(MSG_RUN,isScrolling? 1 : 0 ,isTouch? 1 : 0 ); mHandler.sendMessageDelayed(msg,mScrollTime); } } }; /** *开始自动滚动 */ public void startScroll(){ mHandler.removeMessages(MSG_RUN); isScrolling= true ; Messagemsg=mHandler.obtainMessage(MSG_RUN, 1 ,isTouch? 1 : 0 ); mHandler.sendMessageDelayed(msg,mScrollTime); } /** *停止自动滚动 */ public void stopScroll(){ isScrolling= false ; if (mHandler!= null ){ mHandler.removeMessages(MSG_RUN); } } @Override protected ParcelableonSaveInstanceState(){ Bundlebundle= new Bundle(); bundle.putBoolean( "scroll" ,isScrolling); bundle.putParcelable( "state" , super .onSaveInstanceState()); return bundle; } @Override protected void onRestoreInstanceState(Parcelablestate){ Bundlebundle=(Bundle)state; isScrolling=bundle.getBoolean( "scroll" ); state=bundle.getParcelable( "state" ); if (state!= null ){ super .onRestoreInstanceState(state); } } //@Override //protectedvoidonAttachedToWindow(){ //super.onAttachedToWindow(); //if(isScrolling)mHandler.sendEmptyMessage(MSG_RUN); //} @Override protected void onDetachedFromWindow(){ mHandler.removeMessages(MSG_RUN); super .onDetachedFromWindow(); } /** *设置banner的数据集合 */ public void setAdapter(Adapteradapter){ mAdapter=adapter; mViewPager.setAdapter(adapter); mIndicator.create(adapter.getRealCount()); } /** *获取adapter */ public AdaptergetAdapter(){ return mAdapter; } public int getCurrent(){ return mViewPager.getCurrentItem()+ 1 ; } public void setCurrent( int current){ mViewPager.setCurrentItem(current); } private static class H extends Handler{ private WeakReference<ViewPager>mViewPager; public H(ViewPagerpager){ mViewPager= new WeakReference<>(pager); } public void handleMessage(Messagemsg){ if (mViewPager.get()== null ) return ; boolean isScrolling=msg.arg1== 1 ; boolean isTouch=msg.arg2== 1 ; if (msg.what==MSG_RUN&&isScrolling){ if (!isTouch){ int pos=mViewPager.get().getCurrentItem()+ 1 ; mViewPager.get().setCurrentItem(pos); //sendEmptyMessageDelayed(MSG_RUN,3000); } else { removeMessages(MSG_RUN); } } } } public static abstract class Adapter extends PagerAdapter{ @Override public final int getCount(){ return Integer.MAX_VALUE; } /** *获取真实的数据统计 * *@return */ public abstract int getRealCount(); @Override public final boolean isViewFromObject(Viewarg0,Objectarg1){ return arg0==arg1; } public ObjectgetItem( int position){ return position; } } } BannerViewHelper:(用于解决BannerView和SwipeRefreshLayout的冲突) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 package com.example.p029_banner_lunbo.bannerutils; import android.support.v4.widget.SwipeRefreshLayout; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.ViewGroup; /** *用于解决BannerView和SwipeRefreshLayout的冲突 *@authorgeek * */ public class BannerViewHelper{ private BannerViewmBannerView; private SwipeRefreshLayoutmSwipeRefreshLayout; private VelocityTrackermVelocityTracker; private float mAccuracy= 1 .f; public BannerViewHelper(BannerViewbannerView){ mBannerView=bannerView; mSwipeRefreshLayout=findSwipeRefreshLayout(); } public BannerViewHelper(BannerViewbannerView, float accuracy){ this (bannerView); mAccuracy=accuracy; } public void resolveTouchConflict(MotionEventevent){ if (mSwipeRefreshLayout== null ) return ; setupVelocityTracker(event); switch (event.getAction()){ case MotionEvent.ACTION_MOVE: if (!mSwipeRefreshLayout.isEnabled()) return ; mVelocityTracker.computeCurrentVelocity( 1000 ); if (Math.abs(mVelocityTracker.getXVelocity())> Math.abs(mVelocityTracker.getYVelocity())*mAccuracy){ mSwipeRefreshLayout.setEnabled( false ); } break ; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mSwipeRefreshLayout.setEnabled( true ); recycleVelocityTracker(); default : break ; } } private void setupVelocityTracker(MotionEventevent){ if (mVelocityTracker== null )mVelocityTracker=VelocityTracker.obtain(); mVelocityTracker.addMovement(event); } private void recycleVelocityTracker(){ if (mVelocityTracker!= null ){ mVelocityTracker.clear(); mVelocityTracker.recycle(); mVelocityTracker= null ; } } private SwipeRefreshLayoutfindSwipeRefreshLayout(){ ViewGroupparent=(ViewGroup)mBannerView.getParent(); while (parent!= null &&parent.getId()!=android.R.id.content){ if (parent instanceof SwipeRefreshLayout) return (SwipeRefreshLayout)parent; parent=(ViewGroup)parent.getParent(); } return null ; } } xml布局: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <?xmlversion= "1.0" encoding= "utf-8" ?> <RelativeLayoutxmlns:android= "http://schemas.android.com/apk/res/android" xmlns:app= "http://schemas.android.com/apk/res-auto" android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" > <LinearLayout android:layout_width= "match_parent" android:layout_height= "wrap_content" android:background= "#ccc" android:orientation= "vertical" > <com.example.p029_banner_lunbo.bannerutils.BannerView android:id= "@+id/banner" android:layout_width= "match_parent" android:layout_height= "400dp" app:indicator_position= "center" app:indicator_visible= "false" app:scroll_time= "8000" /> </LinearLayout> <TextView android:id= "@+id/tv_left" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:background= "@drawable/icon_left" /> <TextView android:id= "@+id/tv_right" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_alignParentRight= "true" android:background= "@drawable/icon_right" /> </RelativeLayout> 调用方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 tv_left=(TextView)findViewById(R.id.tv_left); tv_left.setOnClickListener( new View.OnClickListener(){ @Override public void onClick(Viewv){ //左← ToastUtil.showToastShort(MainActivity. this , "左" ); mBannerView.setCurrent(mBannerView.getCurrent()- 2 ); } }); tv_right=(TextView)findViewById(R.id.tv_right); tv_right.setOnClickListener( new View.OnClickListener(){ @Override public void onClick(Viewv){ //右→ ToastUtil.showToastShort(MainActivity. this , "右" ); mBannerView.setCurrent(mBannerView.getCurrent()); } }); mBannerView=(BannerView)findViewById(R.id.banner); Data1(); mBannerView.setAdapter( new BannerAdapter( this ,mList1)); mBannerView.stopScroll(); mBannerView.startScroll(); 代码已经整理好,效果如下图: 图1: 图2: 图2: 地址:https://github.com/geeklx/MyApplication/tree/master/p029_banner_lunbo 附: 本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/liangxiao/1953066,如需转载请自行联系原作者