标签:
循环广告位也是一种非常常见的组件,网上有各种各样的实现,那天看了singwhatiwanna的一种实现,非常简单,然后结合之前见过的一种,稍微整理了一下。
转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/46811889
先看下使用方式:
<com.xjs.demo.view.BannerView android:id="@+id/bannerView" android:layout_width="match_parent" android:layout_height="150dp" android:paddingLeft="10dp" android:paddingRight="10dp"> <android.support.v4.view.ViewPager android:id="@+id/banner_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.xjs.demo.view.DotView android: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 banner = (BannerView) this.findViewById(R.id.bannerView);
banner.setOnBannerClickListener(new OnBannerClickListener(){
@Override
public 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(){
@Override
public 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) {
}
@Override
protected 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;
}
@Override
public 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
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/goldenfish1919/article/details/46811889