標籤:
迴圈廣告位也是一種非常常見的組件,網上有各種各樣的實現,那天看了singwhatiwanna的一種實現,非常簡單,然後結合之前見過的一種,稍微整理了一下。
轉載請標明出處:http://blog.csdn.net/goldenfish1919/article/details/46811889
先看下使用方式:
<com.xjs.demo.view.BannerViewandroid:id="@+id/bannerView"android:layout_width="match_parent"android:layout_height="150dp" android:paddingLeft="10dp"android:paddingRight="10dp"><android.support.v4.view.ViewPagerandroid:id="@+id/banner_viewpager"android:layout_width="match_parent"android:layout_height="match_parent" /><com.xjs.demo.view.DotViewandroid:id="@+id/banner_dotview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom|center_horizontal"android:layout_marginBottom="10dp"app:dot_number="5"app:dot_radius="4dp"app:dot_selected_color="0xffffffff"app:dot_span="8dp"app:dot_unselected_color="0x80ffffff" /></com.xjs.demo.view.BannerView>
自訂的BannerView,內部有兩個子項目,一個是ViewPager,一個是自訂的DotView,使用的時候:
BannerView banner = (BannerView) this.findViewById(R.id.bannerView);banner.setOnBannerClickListener(new OnBannerClickListener(){@Overridepublic void OnBannerClicked(int pos) {Toast.makeText(MainActivity.this, "OnBannerClickListener:" + pos,Toast.LENGTH_SHORT).show();}});int[] imagesSrc = new int[] { R.mipmap.img1, R.mipmap.img2,R.mipmap.img3, R.mipmap.img4, R.mipmap.img5 };banner.update(imagesSrc);可以給Banner添加點擊事件,然後傳遞圖片id,調用banner的update()方法就可以了。
下面重點來看下BannerView:
public class BannerView extends FrameLayout{private DotView mBannerDotView;private ViewPager mBannerViewPager;private BannerAdapter mBannerAdapter;/**當前的position*/private int mBannerPosition = 0;/**Banner點擊後的回調*/private OnBannerClickListener mBannerClickListener;/**自動播放相關*/ private Handler mHandler = new Handler();private Runnable task = new Runnable(){@Overridepublic void run() { mBannerPosition = (mBannerPosition + 1) % mBannerAdapter.getCount(); mBannerViewPager.setCurrentItem(mBannerPosition); Log.d(TAG, "tname:" + Thread.currentThread().getName()); mHandler.postDelayed(task, 3000);}};private static final String TAG = BannerView.class.getSimpleName();public BannerView(Context context) {this(context, null);}public BannerView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public BannerView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);}private void init(Context context) {}@Overrideprotected void onFinishInflate() {super.onFinishInflate();//注意這裡的潛規則mBannerViewPager = (ViewPager)getChildAt(0); mBannerDotView = (DotView)getChildAt(1); mBannerDotView.setDotNumber(0); mBannerAdapter = new BannerAdapter(getContext(), new int[0]); mBannerViewPager.setAdapter(mBannerAdapter); mBannerViewPager.setOnPageChangeListener(mBannerAdapter);}public void update(int[] imagesSrc){if(imagesSrc == null || imagesSrc.length <= 0){return;}mBannerDotView.setDotNumber(imagesSrc.length);mBannerDotView.setSelected(0);mBannerAdapter.update(imagesSrc); mHandler.postDelayed(task, 3000);}private void setIndicator(int position) { position %= mBannerAdapter.getSize(); mBannerDotView.setSelected(position); }private int mDownX; private int mDownY; private long mDownTime;@Override public boolean dispatchTouchEvent(MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { mHandler.removeCallbacks(task); mDownX = (int)event.getX(); mDownY = (int)event.getY(); mDownTime = System.currentTimeMillis(); } else if (action == MotionEvent.ACTION_UP) { if (System.currentTimeMillis() - mDownTime < 500 && Math.abs(mDownX - event.getX()) < 5 && Math.abs(mDownY - event.getY()) < 5) { // 介面回調 if (mBannerClickListener != null) { mBannerClickListener.OnBannerClicked(mBannerPosition%mBannerAdapter.getSize()); } } mHandler.postDelayed(task, 3000); } else if(action == MotionEvent.ACTION_CANCEL){ mHandler.postDelayed(task, 3000); } else if(action == MotionEvent.ACTION_MOVE){ // do nothing } return super.dispatchTouchEvent(event); }private class BannerAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener {private Context mContext; private int[] mImagesSrc; private int mSize; private int mFakeSize; public BannerAdapter(Context context, int[] imagesSrc) { mContext = context; update(mImagesSrc); } public void update(int[] imagesSrc) { if(imagesSrc == null || imagesSrc.length <= 0){ return; } this.mImagesSrc = imagesSrc; this.mSize = imagesSrc.length; this.mFakeSize = mSize * 10; notifyDataSetChanged();}@Override public int getCount() { return mFakeSize; } public int getSize() { return mSize; } @Override public boolean isViewFromObject(View view, Object o) { return view == o; } @Override public Object instantiateItem(ViewGroup container, int position) { position %= mSize; ImageView imageView = new ImageView(mContext); imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); imageView.setScaleType(ScaleType.CENTER_CROP); imageView.setImageResource(mImagesSrc[position]); container.addView(imageView); return imageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public void finishUpdate(ViewGroup container) { int position = mBannerViewPager.getCurrentItem(); Log.d(TAG, "finish update before, position=" + position); if (position == 0) { position = mSize; mBannerViewPager.setCurrentItem(position, false); } else if (position == getCount() - 1) { position = mSize - 1; mBannerViewPager.setCurrentItem(position, false); } Log.d(TAG, "finish update after, position=" + position); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { mBannerPosition = position; setIndicator(position); } @Override public void onPageScrollStateChanged(int state) { } }public interface OnBannerClickListener{public void OnBannerClicked(int pos);}public void setOnBannerClickListener(OnBannerClickListener bannerClickListener) {this.mBannerClickListener = bannerClickListener;}@Overridepublic void onDetachedFromWindow(){mHandler.removeCallbacksAndMessages(null);this.removeAllViews();this.mBannerClickListener = null;super.onDetachedFromWindow();}}然後看下DotView:
public class DotView extends LinearLayout { private int mLittleDotWidth; private int mDotSpan = 36; private float mDotRadius = 6f; private int mDotNumber = 5; private int mCurrent = 0; private int mSelectedColor = 0xFF377BEE; private int mUnSelectedColor = 0xFFC5CEDB; public DotView(Context context) { super(context); } public DotView(Context context, AttributeSet attrs) { super(context, attrs); //擷取自訂的屬性 TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.DotView, 0, 0); if (arr != null) { if (arr.hasValue(R.styleable.DotView_dot_radius)) { mDotRadius = arr.getDimension(R.styleable.DotView_dot_radius, mDotRadius); } if (arr.hasValue(R.styleable.DotView_dot_span)) { mDotSpan = (int) arr.getDimension(R.styleable.DotView_dot_span, mDotSpan); } if(arr.hasValue(R.styleable.DotView_dot_number)){ mDotNumber = (int) arr.getInt(R.styleable.DotView_dot_number, mDotNumber); } mSelectedColor = arr.getColor(R.styleable.DotView_dot_selected_color, mSelectedColor); mUnSelectedColor = arr.getColor(R.styleable.DotView_dot_unselected_color, mUnSelectedColor); arr.recycle(); } mLittleDotWidth = (int) (mDotSpan / 2 + mDotRadius * 2); //把小點畫出來 addDotViews(); } public void setDotNumber(int dotNumber){ this.mDotNumber = dotNumber; addDotViews(); } private void addDotViews(){ setGravity(Gravity.CENTER_HORIZONTAL); setOrientation(HORIZONTAL); removeAllViews(); for (int i = 0; i < mDotNumber; i++) { LittleDot dot = new LittleDot(getContext(), i); if (i == 0) { dot.setColor(mSelectedColor); } else { dot.setColor(mUnSelectedColor); } dot.setLayoutParams(new LayoutParams((int) mLittleDotWidth, (int) mDotRadius * 2, 1)); addView(dot); } } public final void setSelected(int index) { if (index >= getChildCount() || index < 0 || mCurrent == index) { return; } if (mCurrent < getChildCount() && mCurrent >= 0) { ((LittleDot) getChildAt(mCurrent)).setColor(mUnSelectedColor); } ((LittleDot) getChildAt(index)).setColor(mSelectedColor); mCurrent = index; } private class LittleDot extends View { private int mColor; private Paint mPaint; public LittleDot(Context context, int index) { super(context); mPaint = new Paint(); mPaint.setAntiAlias(true); } public void setColor(int color) { if (color == mColor){ return; } mColor = color; invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(mColor); canvas.drawCircle(mLittleDotWidth / 2, mDotRadius, mDotRadius, mPaint); } } public void setSelectedColor(int color) { if (mSelectedColor != color) { mSelectedColor = color; invalidate(); } } public void setUnSelectedColor(int color) { if (mUnSelectedColor != color) { mSelectedColor = color; invalidate(); } } public void setColor(int selectedColor, int unSelectedColor) { if (mSelectedColor != selectedColor || mUnSelectedColor != unSelectedColor) { mSelectedColor = selectedColor; mUnSelectedColor = unSelectedColor; invalidate(); } }}最後是attrs_dotview.xml:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="DotView"> <attr name="dot_number" format="integer" /> <attr name="dot_radius" format="dimension" /> <attr name="dot_span" format="dimension" /> <attr name="dot_unselected_color" format="integer" /> <attr name="dot_selected_color" format="integer" /> </declare-styleable></resources>
這個控制項的優點是:使用起來非常簡單,只需要把圖片傳遞到BannerView的update方法就可以了,而且源碼修改起來也非常簡單。
另外,DotView的實現非常巧妙,非常值得借鑒!
我們不生產代碼,我們只是代碼的搬運工,感謝這些無私奉獻的人:
BannerView參考:http://blog.csdn.net/singwhatiwanna/article/details/46541225
DotView參考:https://github.com/etao-open-source/cube-sdk/tree/master/core/src/in/srain/cube/views/banner
touch攔截:http://blog.csdn.net/wuseyukui/article/details/46627961
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android-迴圈廣告位組件