图片轮播,小圆点可支持居中或居右设置,颜色可自定义,效果如下:
关键代码如下:
public class BannerView extends RelativeLayout {
private boolean isRight;
private int point_size;
private int point_bg;
private int nomalColor;
private int selectColor;
private ViewPager vp;
private RelativeLayout pointLayout;
private List pictureList;
private T t;
//是否在没有图片的情况下占位
private boolean isNeedStaticLocaltion;
//是否轮播
private boolean isPlay = false;
private static int MARGIN = ScreenUtil.dip2px(BaseApplication.getBaseApplication(), 5);
private List myCilcleViews;
private List imageViews;
private UserControal userControal;
private int FLAG = 1;
private int currentPosition = 0;
private float currentX = 0;
private float currentY = 0;
private float MINE_XY = 20;
public static final int MARGIN_LEFtT = ScreenUtil.dip2px(BaseApplication.getBaseApplication(), 19);
private int mDefaultImg = R.mipmap.ic_launcher;
//宽高比例
private float proportion = 0.6F;
private Handler hander = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (null != msg) {
if (msg.what == FLAG) {
hander.removeMessages(FLAG);
vp.setCurrentItem(currentPosition + 1);
hander.sendEmptyMessageDelayed(FLAG, 3000);
}
}
}
};
public BannerView(Context context) {
this(context, null);
}
public BannerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerView);
point_size = (int) array.getDimension(R.styleable.BannerView_point_size, 15);
//point_bg = array.getColor(R.styleable.BannerView_point_bg, 0x00000000);
point_bg = Color.parseColor("#00000000");
isRight = array.getBoolean(R.styleable.BannerView_is_right, false);
isPlay = array.getBoolean(R.styleable.BannerView_is_play, true);
isNeedStaticLocaltion = array.getBoolean(R.styleable.BannerView_is_static_location, true);
nomalColor = array.getColor(R.styleable.BannerView_point_color_unselect, Color.WHITE);
selectColor = array.getColor(R.styleable.BannerView_point_color_select, Color.BLACK);
proportion = array.getFloat(R.styleable.BannerView_banner_proportion, 0.6f);
array.recycle();
}
/**
* 添加ViewPager和指向器布局
*/
private void init() {
vp = new ViewPager(getContext());
pointLayout = new RelativeLayout(getContext());
addView(vp);
addView(pointLayout);
LayoutParams lpVp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.rightMargin = 38;
pointLayout.setBackgroundColor(point_bg);
vp.setLayoutParams(lpVp);
pointLayout.setLayoutParams(lp);
}
/**
* 生成圆点指示器
*/
public void initPoint() {
if (null == pictureList || pictureList.size() < 2) {
return;
}
LinearLayout layout = new LinearLayout(getContext());
int size = pictureList.size();
layout.setOrientation(LinearLayout.HORIZONTAL);
myCilcleViews = new ArrayList<>();
for (int i = 0; i < size; i++) {
MyCilcleView cilcleView = new MyCilcleView(getContext());
layout.addView(cilcleView);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(point_size, point_size);
lp.setMargins(MARGIN, 0, MARGIN, 0);
cilcleView.setLayoutParams(lp);
if (i == 0) {
cilcleView.drawPoint(selectColor, point_size);
} else {
cilcleView.drawPoint(nomalColor, point_size);
}
myCilcleViews.add(cilcleView);
}
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
if (isRight) {
//右侧出现
pointLayout.addView(layout, lp);
} else {
pointLayout.addView(layout, lp);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = (int) (w * proportion);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (i == 0 && child instanceof ViewPager) {
int hM = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
child.measure(widthMeasureSpec, hM);
} else {
int hM = MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST);
child.measure(widthMeasureSpec, hM);
}
}
//setMeasuredDimension(w, h);
int MW = MeasureSpec.makeMeasureSpec(w,MeasureSpec.EXACTLY);
int MH = MeasureSpec.makeMeasureSpec(h,MeasureSpec.EXACTLY);
super.onMeasure(MW, MH);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View v = getChildAt(i);
if (v == vp) {
v.layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
}
if (v == pointLayout) {
pointLayout.layout(0, getMeasuredHeight() - pointLayout.getMeasuredHeight() - 30, getMeasuredWidth(), getMeasuredHeight());
int c = pointLayout.getChildCount();
if (c == 1) {
View view = pointLayout.getChildAt(0);
int w = pointLayout.getMeasuredWidth();
int ww = view.getMeasuredWidth();
int centerW = (w - ww) / 2;
int h = pointLayout.getMeasuredHeight();
int hh = view.getMeasuredHeight();
int centerH = (h - hh) / 2;
if (!isRight) {
view.layout(centerW, centerH, centerW + ww, centerH + hh);
} else {
view.layout(w - ww - 30, centerH, w - 30, centerH + hh);
}
}
}
}
}
public void setConfig(List pictureList, boolean needStaticLocaltion, boolean isPlay, UserControal userControal) {
removeAllViews();
this.pictureList = pictureList;
isNeedStaticLocaltion = needStaticLocaltion;
this.isPlay = isPlay;
this.userControal = userControal;
init();
initPoint();
initVp();
autoPlay();
}
public void notifyBanner(List pictureList) {
removeAllViews();
this.pictureList = pictureList;
init();
initPoint();
initVp();
autoPlay();
}
/**
* 暴露的方法,开始轮播
*/
public void autoPlay() {
if (pictureList == null) {
return;
}
if (!isPlay && pictureList.size() > 1) {
return;
}
hander.sendEmptyMessageDelayed(FLAG, 3000);
}
private void initVp() {
imageViews = new ArrayList<>();
if (pictureList == null || pictureList.size() == 0) {
if (isNeedStaticLocaltion) {
ImageView img = new ImageView(getContext());
img.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
img.setImageResource(mDefaultImg);
img.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageViews.add(img);
initImg(0);
} else {
setVisibility(GONE);
return;
}
} else {
setVisibility(VISIBLE);
int size = pictureList == null ? 0 : pictureList.size() + 1;
if (pictureList != null && pictureList.size() == 1) {
size = 1;
}
for (int i = 0; i < size; i++) {
ImageView img = new ImageView(getContext());
img.setImageResource(mDefaultImg);
img.setScaleType(ImageView.ScaleType.CENTER_CROP);
img.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
imageViews.add(img);
initImg(i);
}
}
BannerAdapter adapter = new BannerAdapter();
vp.setAdapter(adapter);
vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (pictureList == null || pictureList.size() <= 1) {
return;
}
if (position == pictureList.size()) {
vp.setCurrentItem(0, false);
myCilcleViews.get(0).drawPoint(selectColor, point_size);
myCilcleViews.get(position - 1).drawPoint(nomalColor, point_size);
currentPosition = 0;
return;
}
myCilcleViews.get(currentPosition).drawPoint(nomalColor, point_size);
myCilcleViews.get(position).drawPoint(selectColor, point_size);
currentPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
vp.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
currentX = event.getX();
currentY = event.getY();
stop();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (Math.max(Math.abs(currentX - event.getX()), Math.abs(currentY - event.getY())) > MINE_XY) {
//属于滑动了
autoPlay();
} else {
if (userControal != null) {
userControal.pageClick(currentPosition, t);
}
}
break;
}
return false;
}
});
}
private void initImg(int position) {
if (pictureList == null || pictureList.size() == 0) {
imageViews.get(position).setImageResource(mDefaultImg);
return;
}
if (userControal != null) {
if (position < pictureList.size()) {
//imageViews的个数比pircture的数量多1
userControal.initPicture(imageViews.get(position), pictureList.get(position), position);
} else {
userControal.initPicture(imageViews.get(position), pictureList.get(0), 0);
}
}
}
public interface UserControal {
void initPicture(ImageView img, T t, int position);
void pageClick(int position, T t);
}
class BannerAdapter extends PagerAdapter {
@Override
public int getCount() {
return imageViews == null ? 0 : imageViews.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(imageViews.get(position));
return imageViews.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(imageViews.get(position));
}
}
/**
* 暴露的方法,停止轮播
*/
public void stop() {
hander.removeMessages(FLAG);
}
/**
* point
*/
public class MyCilcleView extends TextView {
private int mColor = Color.BLACK;
private int mRadius = 7;
public MyCilcleView(Context context) {
super(context);
}
public MyCilcleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyCilcleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
p.setColor(mColor);
//画笔是否实心
p.setStyle(Paint.Style.FILL);
//抗锯齿
p.setAntiAlias(true);
int mineRadius = Math.min(getWidth() / 2, getHeight() / 2);
if (mRadius > mineRadius) {
mRadius = mineRadius;
}
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mRadius, p);
}
public void drawPoint(int mColor, int mRadius) {
this.mColor = mColor;
this.mRadius = mRadius;
invalidate();
}
}
}
styles.xml 设置属性:
初始化:
/**
* 顶部的轮播图
*/
private void initTopBanner() {
bannerView.setConfig(null, true, true, new BannerView.UserControal() {
@Override
public void initPicture(ImageView img, IndexBannerBean.ListBean indexBannerBean, int position) {
//显示图片
img.setScaleType(ImageView.ScaleType.CENTER_CROP);
Glide.with(getActivity()).load(indexBannerBean.getImage())
.error(R.mipmap.ic_place_banner_0_6)
.skipMemoryCache(true).centerCrop()
.into(img);
}
@Override
public void pageClick(int position, IndexBannerBean.ListBean indexBannerBean) {
//点击事件,根据自己的需求写
}
});
}
@Override
public void onResume() {
super.onResume();
if (bannerView != null) {
bannerView.autoPlay();
}
}
@Override
public void onStop() {
super.onStop();
if (bannerView != null) {
bannerView.stop();
}
}
通过接口获取图片list数据之后调用下面notifyBanner方法就可以使用了:
private List list;
//
bannerView.notifyBanner(list);
xml里面:
is_play:是否轮播
is_right:小圆点是否居右 false:居中 true:居右
is_static_location:是否在没有图片的情况下占位
point_bg:小圆点背景颜色
point_color_select:小圆点选中颜色
point_color_unselect:小圆点未选中颜色
point_size:小圆点直径