前言
最近公司项目中,有一个如下的UI:
可以看到,右侧的圆点,虽然可以直接用布局实现,但是由于很多地方都出现了,所以考虑到复用性不高。可以直接用自定义View来实现,扩展性和复用性都很好,并且这个View也很简单,直接画圆就行了。
最终效果
代码
首先来定义需要用到的自定义属性:
在代码中获取:
public IndicateDotView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr)
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IndicateDotView)
mUnSelectColor = a.getColor(R.styleable.IndicateDotView_indicate_unselect_color, mUnSelectColor)
mSelectColor = a.getColor(R.styleable.IndicateDotView_indicate_select_color, mSelectColor)
mDivideWidth = (int) a.getDimension(R.styleable.IndicateDotView_indicate_divide_width, mDivideWidth)
mDivideColor = a.getColor(R.styleable.IndicateDotView_indicate_divide_color, mDivideColor)
mIsLeastOne = a.getBoolean(R.styleable.IndicateDotView_indicate_is_least_one, mIsLeastOne)
mMargin = (int) a.getDimension(R.styleable.IndicateDotView_indicate_margin, mMargin)
mRadius = (int) a.getDimension(R.styleable.IndicateDotView_indicate_radius, mRadius)
mClickable = a.getBoolean(R.styleable.IndicateDotView_android_clickable, mClickable)
mMaxNumber = a.getInt(R.styleable.IndicateDotView_indicate_max_number, mMaxNumber)
mNumber = a.getInt(R.styleable.IndicateDotView_indicate_number, mNumber)
a.recycle()
mPaint = new Paint()
mPaint.setAntiAlias(true)
}
onDraw()中绘制:
@Override
protected void onDraw(Canvas canvas) {
if(mNumber > mMaxNumber){
if(mIsLeastOne){
mNumber = 1;
}else{
mNumber = 0;
}
}
for (int i = 0; i < mMaxNumber; i++) {
if(i < mNumber){
mPaint.setColor(mSelectColor);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
drawCircle(canvas, i);
}else{
mPaint.setColor(mUnSelectColor);
mPaint.setStyle(Paint.Style.FILL);
drawCircle(canvas, i);
if(mDivideColor != -1){
mPaint.setColor(mDivideColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mDivideWidth);
drawCircle(canvas, i);
}
}
}
}
代码很简单,就是根据最大圆点数循环绘制圆以及边框,绘制圆的代码如下:
private void drawCircle(Canvas canvas, int i){
canvas.drawCircle(getPaddingLeft() + mRadius + mDivideWidth + (((mRadius * 2)
+ (mDivideWidth * 2) + mMargin) * i), getHeight() / 2, mRadius, mPaint);
}
最后在onMeasure()计算宽高:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
if(widthMode != MeasureSpec.EXACTLY){
width = mMaxNumber * (mRadius * 2 + mDivideWidth * 2 + mMargin) + getPaddingLeft() + getPaddingRight();
}
if(heightMode != MeasureSpec.EXACTLY){
height = mRadius * 2 + mDivideWidth * 2 + getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width,
heightMode == MeasureSpec.EXACTLY ? heightSize : height);
}
源码下载
GitHub地址:github.com/Airsaid/Ind…