Android 自定义控件之圆点指示器 View (IndicateDotView)

转载请标明出处: http://blog.csdn.net/airsaid/article/details/52904344
本文出自:周游的博客

前言

最近公司项目中,有一个如下的UI:
这里写图片描述
可以看到,右侧的圆点,虽然可以直接用布局实现,但是由于很多地方都出现了,所以考虑到复用性不高。可以直接用自定义View来实现,扩展性和复用性都很好,并且这个View也很简单,直接画圆就行了。

最终效果

这里写图片描述

代码

首先来定义需要用到的自定义属性:

<!--圆点指示器View属性-->
<declare-styleable name="IndicateDotView">
    <!--已选中指示点颜色-->
    <attr name="indicate_select_color" format="color"/>
    <!--未选中指示点颜色-->
    <attr name="indicate_unselect_color" format="color"/>
    <!--指示点之间的间距-->
    <attr name="indicate_margin" format="dimension"/>
    <!--指示点半径-->
    <attr name="indicate_radius" format="dimension"/>
    <!--指示点被选中个数-->
    <attr name="indicate_number" format="integer"/>
    <!--指示点最大个数-->
    <attr name="indicate_max_number" format="integer"/>
    <!--是否最少保留一个指示点--> 
    <attr name="indicate_is_least_one" format="boolean"/>
    <!--边框颜色-->
    <attr name="indicate_divide_color" format="color"/>
    <!--边框宽度-->
    <attr name="indicate_divide_width" format="dimension"/>
    <!--是否可点击-->
    <attr name="android:clickable" />
</declare-styleable>

在代码中获取:

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地址:https://github.com/Airsaid/IndicateDotView

发布了55 篇原创文章 · 获赞 117 · 访问量 30万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览