美文网首页日志Android开发经验谈Android知识
PercentageCircle (显示百分比)控件

PercentageCircle (显示百分比)控件

作者: 到了我的周末 | 来源:发表于2017-11-03 12:30 被阅读55次

    项目中需要同步硬件设备的数据,显示大概百分比和实时数据。自定义的控件。

    简介

    @效果图|center|160*260
    • 用户目前数量。
    • 设置单位。
    • 根据颜色来判断目前所占总数的大概百分比。

    特点

    1. 项目中使用
      可以在代码xml中设置 当前数目和背景的颜色,当前数目单位字体颜色大小
      @如图xml|center|300*150
      @代码中|center|300*250

    使用简单,可以直接在xml中或者动态代码中设置对应的属性,代码中设置的属性会覆盖xml中的属性。

    功能的设计

    1. 按照要求宽和高相同onMeasure的代码
    //测量控件的大小,以为是一个圆,所以用最小的数字作为他们的直径的长度。
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
            setMeasuredDimension(size, size);
        }
    
    1. 绘制onDraw(),一条直线,然后去旋转

    • 画直线
    canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, mLineLength, mPaint);
    

    起始点为(width/2,0)就是控件的中心点的正上方,坐标的-90°位置。

    • 旋转
     canvas.rotate(mDrgees, getWidth() / 2, getHeight() / 2);
    

    以控件的中心点为原点,以设定的角度去旋转,在for中循环执行。

    • 颜色
      占有百分比和背景颜色,在for循环前设定。如下代码
    //设置未被选中的直线的颜色。
           mPaint.setColor(mUnSelectColor);
            for (int i = 0; i < mSumLine - mSelectLine; i++) {
                canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, mLineLength, mPaint);
                canvas.rotate(mDrgees, getWidth() / 2, getHeight() / 2);
            }
            //设置数量字体的颜色
            mPaint.setColor(mNumColor);
            if (!TextUtils.isEmpty(mNumShow)) {
                mPaint.setTextSize(mNumTextSize);
                mPaint.getTextBounds(mNumShow, 0, mNumShow.length(), mNumShowRect);
            }
    
    • 字体
      设定字体的颜色,和范围。
    //设置数量字体的颜色
            mPaint.setColor(mNumColor);
            if (!TextUtils.isEmpty(mNumShow)) {
                mPaint.setTextSize(mNumTextSize);
                mPaint.getTextBounds(mNumShow, 0, mNumShow.length(), mNumShowRect);
            }
            if(!TextUtils.isEmpty(mNumShow)){
                canvas.drawText(mNumShow, (getWidth() / 2 - mNumShowRect.width() / 2), (getHeight() / 2 + mNumShowRect.height() / 2)
                        , mPaint);
            }
    

    以上就是主要的代码实现。主要就是ondraw()中代码的实现。

    属性和样式

    属性 对应变量 类型 默认值
    选中直线颜色 select_color color Color.BLUE
    未选中直线颜色 select_color color Color.GRAY
    数量字体颜色 num_color color Color.BLACK
    单位字体颜色 unit_color color Color.BLACK
    数量文字 num_text String --
    单位文字 unit_text String --
    数量文字大小 num_text_size dimension 30px
    数量文字大小 unit_text_size dimension 18px
    总直线数目 all_line_num integer 36
    直线长度 line_height dimension 10px
    直线宽度 line_width dimension 2px

    源码

    1. 控件代码
    public class PercentageCircle extends View {
        //初始化画笔
        private Paint mPaint;
    
        //设置没有被选中的颜色。
        private int mSelectColor;
    
        //设置选中后的颜色。
        private int mUnSelectColor;
    
        //设置数字的颜色
        private int mNumColor;
    
        //设置单位的颜色
        private int mUnitColor;
    
        //设置单位字体的大小。
        private float mUnitTextSize;
    
        //设置数目字体的大小。
        private float mNumTextSize;
    
        //总的数目
        private int mSumLine;
    
        //旋转的角度
        private float mDrgees;
    
        //dp转换为px。。line的长度
        private float mLineLength;
    
        //line的宽度。
        private float mLineWidth;
    
        //初始化被选中的数目
        private int mSelectLine = 0;
    
        //设置控件的单位
        private String mUnit;
        //设置控件的单位
        private String mNumShow;
    
    
        //设置字体的范围
        private Rect mUnitRect;
        //设置字体的范围
        private Rect mNumShowRect;
    
        public PercentageCircle(Context context) {
            this(context, null);
        }
    
        public PercentageCircle(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public PercentageCircle(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            //属性集合
    
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PercentageCircle);
    
            //设置没被选中的默认的颜色为灰色。
            mUnSelectColor = array.getColor(R.styleable.PercentageCircle_unselect_color, Color.GRAY);
    
            //设置默认被选中的颜色为蓝色。
            mSelectColor = array.getColor(R.styleable.PercentageCircle_select_color, Color.BLUE);
    
            //设置字体和单位的默认的颜色为灰色。
            mNumColor = array.getColor(R.styleable.PercentageCircle_num_color, Color.BLACK);
            mUnitColor = array.getColor(R.styleable.PercentageCircle_unit_color, Color.BLACK);
    
            //设置字体的大小和默认值
            mUnitTextSize = array.getDimensionPixelOffset(R.styleable.PercentageCircle_unit_text_size, (int) dp2px(18));
            mNumTextSize = array.getDimensionPixelOffset(R.styleable.PercentageCircle_num_text_size, (int) dp2px(30));
    
            //设置总的数目
            mSumLine = array.getInt(R.styleable.PercentageCircle_all_line_num, 36);
    
            //单位的文本
            mUnit = array.getString(R.styleable.PercentageCircle_unit_text);
            mNumShow = array.getString(R.styleable.PercentageCircle_num_text);
    
            //设置直线的宽度
            mLineWidth = array.getDimensionPixelOffset(R.styleable.PercentageCircle_line_width, (int) dp2px(2));
            //长度
            mLineLength = array.getDimensionPixelOffset(R.styleable.PercentageCircle_line_length, (int) dp2px(10));
            array.recycle();
    
    
            //实例化画笔
            mPaint = new Paint();
            //抗锯齿
            mPaint.setAntiAlias(true);
            //设置宽度
            mPaint.setStrokeWidth(mLineWidth);
    
            //设置数目字体的范围,用来得到 字体的宽和高。
            mNumShowRect = new Rect();
            //设置单位字体的范围。
            mUnitRect = new Rect();
        }
    
        //测量控件的大小,以为是一个圆,所以用最小的数字作为他们的直径的长度。
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
            setMeasuredDimension(size, size);
        }
    
        //绘制控件
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            //设置每个间隔的旋转的角度.等于360/总数目的个数。
            mDrgees = 360 / mSumLine;
            Log.i("111", mDrgees + "hha");
    
            canvas.save();
            //设置被选中的直线的颜色
            mPaint.setColor(mSelectColor);
            for (int i = 0; i < mSelectLine; i++) {
                canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, mLineLength, mPaint);
                canvas.rotate(mDrgees, getWidth() / 2, getHeight() / 2);
            }
            //设置未被选中的直线的颜色。
            mPaint.setColor(mUnSelectColor);
            for (int i = 0; i < mSumLine - mSelectLine; i++) {
                canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, mLineLength, mPaint);
                canvas.rotate(mDrgees, getWidth() / 2, getHeight() / 2);
            }
    
            //设置数量字体的颜色
            mPaint.setColor(mNumColor);
            if (!TextUtils.isEmpty(mNumShow)) {
                mPaint.setTextSize(mNumTextSize);
                mPaint.getTextBounds(mNumShow, 0, mNumShow.length(), mNumShowRect);
            }
            if(!TextUtils.isEmpty(mNumShow)){
                canvas.drawText(mNumShow, (getWidth() / 2 - mNumShowRect.width() / 2), (getHeight() / 2 + mNumShowRect.height() / 2)
                        , mPaint);
            }
    //        canvas.drawText(mNumShow, (getWidth() / 2 - mNumShowRect.width() / 2), (getHeight() / 2 + mNumShowRect.height() / 2)
    //                , mPaint);
            Log.i("111",mNumShow +"---"+ (getWidth() / 2 - mNumShowRect.width() / 2) + "===" + (getHeight() / 2 + mNumShowRect.height() / 2));
    
            //设置单位字体的颜色。
            mPaint.setColor(mUnitColor);
            if (!TextUtils.isEmpty(mUnit)) {
                mPaint.setTextSize(mUnitTextSize);
                mPaint.getTextBounds(mUnit, 0, mUnit.length(), mUnitRect);
            }
            if(!TextUtils.isEmpty(mUnit)){
                canvas.drawText(mUnit, getWidth() / 2 - mUnitRect.width() / 2, getHeight() / 2 + mNumShowRect.height() / 2
                        + mUnitRect.height() / 2 + dp2px(20), mPaint);
            }
    
    
            canvas.restore();
        }
    
        //设置被选中的数目。
        public void setSumSelect(int num) {
            if (num > mSumLine) {
                num = mSumLine;
            }
            if (num < 0) {
                num = 0;
            }
            this.mSelectLine = num;
            invalidate();
        }
    
        //设置单位文字
        public void setUnit(String unit) {
            if (!TextUtils.isEmpty(unit)) {
                this.mUnit = unit;
            }
            invalidate();
        }
    
        //设置单位颜色
        public void setUnitColor(int color) {
            if (!TextUtils.isEmpty(mUnit)) {
                this.mUnitColor = color;
            }
            invalidate();
        }
    
        //设置单位字体大小
        public void setUnitTextSize(int size) {
            if (!TextUtils.isEmpty(mUnit)) {
                this.mUnitTextSize = size;
            }
            invalidate();
        }
    
        //设置数量的文字
        public void setNumText(String numText) {
            if (!TextUtils.isEmpty(numText)) {
                this.mNumShow = numText;
            }
            invalidate();
        }
    
        //设置没有被选中的颜色
        public void setUnSelectColor(int color) {
            this.mUnSelectColor = color;
        }
    
        //设置被选中的颜色
        public void setSelectColor(int color) {
            this.mSelectColor = color;
        }
    
        //设置数量颜色
        public void setmNumColor(int color) {
            if (!TextUtils.isEmpty(String.valueOf(color))) {
                this.mNumColor = color;
            }
            invalidate();
        }
    
        //设置数量字体大小
        public void setNumTextSize(int size) {
            if (!TextUtils.isEmpty(String.valueOf(size))) {
                this.mNumTextSize = size;
            }
            invalidate();
        }
    
        //设置数目
        public void setNumShow(String show) {
            if (!TextUtils.isEmpty(show)) {
                this.mNumShow = show;
            }
            invalidate();
        }
    
        //设置直线的宽度。
        public void setLineWidth(int width) {
            this.mLineWidth = width;
        }
    
        //设置直线的高度。
        public void setLineLength(int length) {
            this.mLineLength = length;
        }
    
        //dp转化为px
        private float dp2px(float dpVal) {
            return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    dpVal, getResources().getDisplayMetrics());
        }
    }
    
    
    1. 属性
    <declare-styleable name="PercentageCircle">
            <!--被选中的文字的颜色-->
            <attr name="select_color" format="color"/>
            <!--没有被选中的文字的颜色-->
            <attr name="unselect_color" format="color"/>
            <!--数量单位的文字的颜色-->
            <attr name="unit_color" format="color"/>
            <!--数量文字的颜色-->
            <attr name="num_color" format="color"/>
    
    
            <!--数量单位的文字-->
            <attr name="unit_text" format="string"/>
            <!--数量的字体size大小-->
            <attr name="num_text" format="string"/>
    
            <!--数量单位的文字-->
            <attr name="unit_text_size" format="dimension"/>
            <!--数量的字体size大小-->
            <attr name="num_text_size" format="dimension"/>
    
            <!--总数目的直线的条数-->
            <attr name="all_line_num" format="integer"/>
            
            <!--间隔的角度的大小-->
            <!--<attr name="interval_degree" format="integer"/>-->
            
            <!--直线的宽度的大小-->
            <attr name="line_width" format="dimension"/>
    
            <!--直线的长度-->
            <attr name="line_length" format="dimension"/>
        </declare-styleable>
    
    • 代码
    //可以动态的设置自定义view的属性。也可以在xml中设置属性。
            //设置被选中的数量。
            percentageCircle.setSumSelect(20);
            /**
             * 1:可以直接在代码中动态设置。
             * 2:动态设置的会把 xml中设置的 数量和文字覆盖掉。
             */
            //设置显示的数量。
            percentageCircle.setNumShow(60+"");
            //设置单位文字
            percentageCircle.setUnit("口数");
            percentageCircle.setUnSelectColor(Color.BLACK);
            percentageCircle.setSelectColor(Color.RED);
            percentageCircle.setUnitColor(Color.GREEN);
            percentageCircle.setmNumColor(Color.MAGENTA);
    
    源码

    Github的源码地址-->PercentageCircle

    使用

    在model的build.gradle中添加
    'compile 'com.cyy:PercentageCircle:1.0.2'

    相关文章

      网友评论

        本文标题:PercentageCircle (显示百分比)控件

        本文链接:https://www.haomeiwen.com/subject/hwhtmxtx.html