年费比例控件

作者: aositeluoke | 来源:发表于2017-09-16 13:57 被阅读8次

    项目年费控件UI图


    image.png

    实现效果


    年费.gif
    控件分析(从里到外进行分析,最后分析指针)

    1、中间有个红色圆点,抽取颜色和半径
    2、白色圆环,抽取圆环宽度、圆环颜色
    3、包围白色圆环的圆环宽度和颜色
    4、指针指向的圆环颜色和宽度
    5、进度圆弧的宽度、颜色和底色
    6、最外边的圆弧颜色和宽度
    7、指针颜色、长度和宽度
    8、进度圆弧和最外层圆弧的距离
    9、包围白色圆环的圆环和指针指向的圆环距离
    10、绘制进度圆弧的开始角度为-225,扫描的最大度数为270
    11、绘制指针时、先把画布旋转一定的角度再绘制

    自定义属性
     <declare-styleable name="YearCostView">
    
            <!--centerPoint-->
            <attr name="center_point_color" format="color" />
            <attr name="center_point_radius" format="dimension" />
    
            <!--中间圆环的颜色和宽度-->
            <attr name="center_ring_color" format="color" />
            <attr name="center_ring_width" format="dimension" />
    
            <!--包裹中心圆环的圆环-->
            <attr name="wraper_center_ring_color" format="color" />
            <attr name="wraper_center_ring_width" format="dimension" />
    
    
            <!--指针-->
            <attr name="line_width" format="dimension" />
            <attr name="line_color" format="color" />
    
    
            <!--inner圆环-->
            <attr name="inner_ring_color" format="color" />
            <attr name="inner_ring_width" format="dimension" />
    
            <!--target圆环-->
            <attr name="target_ring_color" format="color" />
            <attr name="target_ring_width" format="dimension" />
            <attr name="target_bottom_ring_color" format="color" />
    
            <!--out圆环-->
            <attr name="out_ring_color" format="color" />
            <attr name="out_ring_width" format="dimension" />
    
            <!--距离-->
            <attr name="inner_distance" format="dimension" />
            <attr name="out_distance" format="dimension" />
    
        </declare-styleable>
    
    获取自定义属性
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YearCostView, defStyleAttr, 0);
            int n = a.getIndexCount();
            for (int i = 0; i < n; i++) {
                int attr = a.getIndex(i);
    
                switch (attr) {
    
                    //中心圆点
                    case R.styleable.YearCostView_center_point_radius:
                        centerPointRadius = a.getLayoutDimension(attr, centerPointRadius);
                        break;
                    case R.styleable.YearCostView_center_point_color:
                        centerPointColor = a.getColor(attr, Color.parseColor("#f05b48"));
                        break;
                    //中心圆环
                    case R.styleable.YearCostView_center_ring_width:
                        centerRingWidth = a.getLayoutDimension(attr, centerRingWidth);
                        break;
                    case R.styleable.YearCostView_center_ring_color:
                        centerRingColor = a.getColor(attr, ContextCompat.getColor(getContext(), android.R.color.white));
                        break;
    
                    //包裹中心圆环的圆环
                    case R.styleable.YearCostView_wraper_center_ring_width:
                        wraperCenterRingWidth = a.getLayoutDimension(attr, wraperCenterRingWidth);
                        break;
                    case R.styleable.YearCostView_wraper_center_ring_color:
                        wraperCenterRingColor = a.getColor(attr, Color.parseColor("#35383c"));
                        break;
    
                    //指针
                    case R.styleable.YearCostView_line_width:
                        lineWidth = a.getLayoutDimension(attr, lineWidth);
                        break;
                    case R.styleable.YearCostView_line_color:
                        lineColor = a.getColor(attr, Color.parseColor("#f05b48"));
                        break;
    
                    //inner ring
                    case R.styleable.YearCostView_inner_ring_width:
                        innerRingWidth = a.getLayoutDimension(attr, innerRingWidth);
                        break;
                    case R.styleable.YearCostView_inner_ring_color:
                        innerRingColor = a.getColor(attr, Color.parseColor("#25292c"));
                        break;
    
                    //target ring
                    case R.styleable.YearCostView_target_ring_width:
                        targetRingWidth = a.getLayoutDimension(attr, targetRingWidth);
                        break;
                    case R.styleable.YearCostView_target_ring_color:
                        targetRingColor = a.getColor(attr, Color.parseColor("#f05b48"));
                        break;
                    case R.styleable.YearCostView_target_bottom_ring_color:
                        targetBottomRingColor = a.getColor(attr, Color.parseColor("#303438"));
                        break;
    
                    //out ring
                    case R.styleable.YearCostView_out_ring_width:
                        outRingWidth = a.getLayoutDimension(attr, outRingWidth);
                        break;
                    case R.styleable.YearCostView_out_ring_color:
                        outRingColor = a.getColor(attr, Color.parseColor("#75777a"));
                        break;
    
                    //距离
                    case R.styleable.YearCostView_out_distance:
                        outDistance = a.getLayoutDimension(attr, outDistance);
                        break;
                    case R.styleable.YearCostView_inner_distance:
                        innerDistance = a.getLayoutDimension(attr, innerDistance);
                        break;
                }
            }
            a.recycle();
    
    自定义控件完整代码
    /**
     * 类描述:年费View
     * 作者:xues
     * 时间:2017年09月12日
     */
    
    public class YearCostView extends View {
    
        //中心圆环(白色圆环)
        private Paint centerRingPaint;
        private int centerRingWidth = 2 * 6;
        private int centerRingColor;
        private RectF centerRingRectF;
    
        //包裹中心圆环的圆环
        private int wraperCenterRingColor;
        private Paint wraperCenterRingPaint;
        private int wraperCenterRingWidth = 4 * 6;
        private RectF wraperCenterRingRectF;
    
    
        //在目标圆环里边的圆环
        private int innerRingColor;
        private Paint innerRingPaint;
        private int innerRingWidth = 1 * 6;
        private RectF innerRingRectF;
    
        //目标圆环(红色圆环)
        private int targetRingColor;
        private Paint targetRingPaint;
        private int targetRingWidth = 16 * 6;
        private RectF targetRingRectF;
    
        //目标圆环压着的圆环(红色圆环压着的圆环)
        private int targetBottomRingColor;
        private Paint targetBottomRingPaint;
        private int targetBottomRingWidth = 16 * 6;
        private RectF targetBottomRingRectF;
    
    
        //在目标圆环外面的圆环
        private int outRingColor;
        private Paint outRingPaint;
        private int outRingWidth = 1 * 6;
        private RectF outRingRectF;
    
    
        //指针
        private int lineColor;
        private Paint linePaint;
        private int lineWidth = 2 * 6;
    
        //中心红点
        private int centerPointColor;
        private Paint centerPointPaint;
        private int centerPointRadius = 1 * 6;
    
    
        //圆环与圆环之间的距离
        private int innerDistance = 120;
        private int outDistance = 8;
        private RotateAnimation mSweepAnim;//扫描动画
    
        public YearCostView(Context context) {
            this(context, null);
        }
    
        public YearCostView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public YearCostView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YearCostView, defStyleAttr, 0);
            int n = a.getIndexCount();
            for (int i = 0; i < n; i++) {
                int attr = a.getIndex(i);
    
                switch (attr) {
    
                    //中心圆点
                    case R.styleable.YearCostView_center_point_radius:
                        centerPointRadius = a.getLayoutDimension(attr, centerPointRadius);
                        break;
                    case R.styleable.YearCostView_center_point_color:
                        centerPointColor = a.getColor(attr, Color.parseColor("#f05b48"));
                        break;
                    //中心圆环
                    case R.styleable.YearCostView_center_ring_width:
                        centerRingWidth = a.getLayoutDimension(attr, centerRingWidth);
                        break;
                    case R.styleable.YearCostView_center_ring_color:
                        centerRingColor = a.getColor(attr, ContextCompat.getColor(getContext(), android.R.color.white));
                        break;
    
                    //包裹中心圆环的圆环
                    case R.styleable.YearCostView_wraper_center_ring_width:
                        wraperCenterRingWidth = a.getLayoutDimension(attr, wraperCenterRingWidth);
                        break;
                    case R.styleable.YearCostView_wraper_center_ring_color:
                        wraperCenterRingColor = a.getColor(attr, Color.parseColor("#35383c"));
                        break;
    
                    //指针
                    case R.styleable.YearCostView_line_width:
                        lineWidth = a.getLayoutDimension(attr, lineWidth);
                        break;
                    case R.styleable.YearCostView_line_color:
                        lineColor = a.getColor(attr, Color.parseColor("#f05b48"));
                        break;
    
                    //inner ring
                    case R.styleable.YearCostView_inner_ring_width:
                        innerRingWidth = a.getLayoutDimension(attr, innerRingWidth);
                        break;
                    case R.styleable.YearCostView_inner_ring_color:
                        innerRingColor = a.getColor(attr, Color.parseColor("#25292c"));
                        break;
    
                    //target ring
                    case R.styleable.YearCostView_target_ring_width:
                        targetRingWidth = a.getLayoutDimension(attr, targetRingWidth);
                        break;
                    case R.styleable.YearCostView_target_ring_color:
                        targetRingColor = a.getColor(attr, Color.parseColor("#f05b48"));
                        break;
                    case R.styleable.YearCostView_target_bottom_ring_color:
                        targetBottomRingColor = a.getColor(attr, Color.parseColor("#303438"));
                        break;
    
                    //out ring
                    case R.styleable.YearCostView_out_ring_width:
                        outRingWidth = a.getLayoutDimension(attr, outRingWidth);
                        break;
                    case R.styleable.YearCostView_out_ring_color:
                        outRingColor = a.getColor(attr, Color.parseColor("#75777a"));
                        break;
    
                    //距离
                    case R.styleable.YearCostView_out_distance:
                        outDistance = a.getLayoutDimension(attr, outDistance);
                        break;
                    case R.styleable.YearCostView_inner_distance:
                        innerDistance = a.getLayoutDimension(attr, innerDistance);
                        break;
                }
            }
            a.recycle();
            initView();
        }
    
        /**
         * 初始化参数
         */
        private void initView() {
            initPaint();
            //初始化动画并设置动画持续时间为1000毫秒==1秒
            mSweepAnim = new RotateAnimation();
            mSweepAnim.setDuration(1000);
        }
    
        float centerX;//中心点x
    
        //初始化矩形
        private void initRectF() {
            //中心圆环
            float leftOrTop = centerX - centerRingWidth / 2F - centerPointRadius;
            float rightOrBottom = centerX + centerRingWidth / 2F + centerPointRadius;
            centerRingRectF = new RectF(leftOrTop, leftOrTop, rightOrBottom, rightOrBottom);
            //包围中心圆环的圆环
            leftOrTop = centerX - centerRingWidth - centerPointRadius - wraperCenterRingWidth / 2F;
            rightOrBottom = centerX + centerRingWidth + centerPointRadius + wraperCenterRingWidth / 2F;
            wraperCenterRingRectF = new RectF(leftOrTop, leftOrTop, rightOrBottom, rightOrBottom);
            //inner圆环
            leftOrTop = centerX - centerPointRadius - centerRingWidth - wraperCenterRingWidth - innerDistance - innerRingWidth / 2F;
            rightOrBottom = centerX + centerPointRadius + centerRingWidth + wraperCenterRingWidth + innerDistance + innerRingWidth / 2F;
            innerRingRectF = new RectF(leftOrTop, leftOrTop, rightOrBottom, rightOrBottom);
    
            //目标圆环
            leftOrTop = centerX - centerPointRadius - centerRingWidth - wraperCenterRingWidth - innerDistance - innerRingWidth - outDistance - targetRingWidth / 2F;
            rightOrBottom = centerX + centerPointRadius + centerRingWidth + wraperCenterRingWidth + innerDistance + innerRingWidth + outDistance + targetRingWidth / 2F;
            targetRingRectF = new RectF(leftOrTop, leftOrTop, rightOrBottom, rightOrBottom);
            targetBottomRingRectF = new RectF(leftOrTop, leftOrTop, rightOrBottom, rightOrBottom);
    
            //out圆环
            leftOrTop = centerX - centerPointRadius - centerRingWidth - wraperCenterRingWidth - innerDistance - innerRingWidth - outDistance * 2 - targetRingWidth - outRingWidth / 2F;
            rightOrBottom = centerX + centerPointRadius + centerRingWidth + wraperCenterRingWidth + innerDistance + innerRingWidth + outDistance * 2 + targetRingWidth + outRingWidth / 2F;
            outRingRectF = new RectF(leftOrTop, leftOrTop, rightOrBottom, rightOrBottom);
    
        }
    
        /**
         * 从里边向外初始化画笔
         */
        private void initPaint() {
            //中心点
            centerPointPaint = new Paint();
            centerPointPaint.setAntiAlias(true);
            centerPointPaint.setStrokeWidth(2 * centerPointRadius);
            centerPointPaint.setColor(centerPointColor);
            centerPointPaint.setStyle(Paint.Style.FILL);
            //中心圆环
            centerRingPaint = new Paint();
            centerRingPaint.setAntiAlias(true);
            centerRingPaint.setStrokeWidth(centerRingWidth);
            centerRingPaint.setColor(centerRingColor);
            centerRingPaint.setStyle(Paint.Style.STROKE);
            //包裹中心圆环的圆环
            wraperCenterRingPaint = new Paint();
            wraperCenterRingPaint.setAntiAlias(true);
            wraperCenterRingPaint.setStrokeWidth(wraperCenterRingWidth);
            wraperCenterRingPaint.setColor(wraperCenterRingColor);
            wraperCenterRingPaint.setStyle(Paint.Style.STROKE);
    
            //inner圆环
            innerRingPaint = new Paint();
            innerRingPaint.setAntiAlias(true);
            innerRingPaint.setStrokeWidth(innerRingWidth);
            innerRingPaint.setColor(innerRingColor);
            innerRingPaint.setStyle(Paint.Style.STROKE);
    
    
            //目标圆环压住的圆环
            targetBottomRingPaint = new Paint();
            targetBottomRingPaint.setAntiAlias(true);
            targetBottomRingPaint.setStrokeWidth(targetRingWidth);
            targetBottomRingPaint.setColor(targetBottomRingColor);
            targetBottomRingPaint.setStyle(Paint.Style.STROKE);
    
            //目标圆环
            targetRingPaint = new Paint();
            targetRingPaint.setAntiAlias(true);
            targetRingPaint.setStrokeWidth(targetRingWidth);
            targetRingPaint.setColor(targetRingColor);
            targetRingPaint.setStyle(Paint.Style.STROKE);
    
            //外部圆环
            outRingPaint = new Paint();
            outRingPaint.setAntiAlias(true);
            outRingPaint.setStrokeWidth(outRingWidth);
            outRingPaint.setColor(outRingColor);
            outRingPaint.setStyle(Paint.Style.STROKE);
    
            //指针
            linePaint = new Paint();
            linePaint.setAntiAlias(true);
            linePaint.setStrokeWidth(lineWidth);
            linePaint.setColor(lineColor);
            linePaint.setStyle(Paint.Style.FILL);
    
        }
    
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int wSize = 0;
    
    
            //match_parent or set value
            if (widthMode == MeasureSpec.EXACTLY) {
                wSize = widthSize;
            } else {
                //wrap_content
                if (widthMode == MeasureSpec.AT_MOST) {
                    wSize = 2 * (centerPointRadius + centerRingWidth + wraperCenterRingWidth + innerDistance + innerRingWidth + outDistance * 2 + targetRingWidth);
                }
            }
    
    
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int hSize = 0;
    
            //match_parent or set value
            if (heightMode == MeasureSpec.EXACTLY) {
                hSize = heightSize;
            } else {
                //wrap_content
                if (heightMode == MeasureSpec.AT_MOST) {
                    hSize = 2 * (centerPointRadius + centerRingWidth + wraperCenterRingWidth + innerDistance + innerRingWidth + outDistance * 2 + targetRingWidth);
                    ;
                }
            }
    
            centerX = widthSize / 2f;
            initRectF();//初始化灰色圆环和多颜色圆环矩形
            setMeasuredDimension(wSize, hSize);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
    
            //绘制中心点
            canvas.save();
            canvas.restore();
    
            //绘制包裹中心圆环的圆环
            canvas.save();
            canvas.drawArc(wraperCenterRingRectF, 0, 360, false, wraperCenterRingPaint);
            canvas.restore();
    
            //绘制inner圆环
            canvas.save();
            canvas.drawArc(innerRingRectF, 0, 360, false, innerRingPaint);
            canvas.restore();
            //绘制指针
            canvas.save();
            canvas.translate(centerX, centerX);
            canvas.rotate(mSweepAngle + 135);
            canvas.drawLine(-2, -2, centerPointRadius + centerRingWidth + wraperCenterRingWidth + innerDistance + innerRingWidth, 0, linePaint);
            canvas.restore();
    
            //绘制中心圆环
            canvas.save();
            canvas.drawArc(centerRingRectF, 0, 360, false, centerRingPaint);
            canvas.restore();
    
    
            //绘制红色圆点
            canvas.save();
            canvas.drawCircle(centerX, centerX, centerPointRadius, centerPointPaint);
            canvas.restore();
    
    
            //绘制目标圆环压住的圆环
            canvas.save();
            canvas.drawArc(targetBottomRingRectF, -225, 270, false, targetBottomRingPaint);
            canvas.restore();
    
            //绘制目标圆环
            canvas.save();
            canvas.drawArc(targetRingRectF, -225, mSweepAngle, false, targetRingPaint);
            canvas.restore();
    
    
            //绘制out圆环
            canvas.save();
            canvas.drawArc(outRingRectF, -226, 272, false, outRingPaint);
            canvas.restore();
        }
    
    
        float mSweepAngle;
    
        /**
         * 自定义旋转动画
         */
        public class RotateAnimation extends Animation {
            /**
             * Initializes expand collapse animation, has two types, collapse (1) and expand (0).
             */
            public RotateAnimation() {
            }
    
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                super.applyTransformation(interpolatedTime, t);
                //interpolatedTime 范围:0到1
                mSweepAngle = BigDecimalUtil.mul(interpolatedTime, BigDecimalUtil.mul(BigDecimalUtil.div(curMoney, totalMoney), 270F));//当前时间扫描的角度
                postInvalidate();//重绘
            }
        }
    
    
        float curMoney, totalMoney;
    
        /**
         * 设置价格
         *
         * @param curMoney   当前价格
         * @param totalMoney 总金额
         */
        public void setMoney(float curMoney, float totalMoney) {
            this.curMoney = curMoney;
            this.totalMoney = totalMoney;
            startAnimation(mSweepAnim);
        }
    }
    
    使用篇

    在布局中使用自定义控件

    <包名.YearCostView
            android:id="@+id/yearCostView"
            android:layout_width="@dimen/px480dp"
            android:layout_height="@dimen/px480dp"
            android:layout_gravity="center"
            android:background="#191d21"
            app:center_point_color="#f05b48"
            app:center_point_radius="@dimen/px6dp"
            app:center_ring_color="#ffffff"
            app:center_ring_width="@dimen/px6dp"
            app:inner_distance="@dimen/px100dp"
            app:inner_ring_color="#25292c"
            app:inner_ring_width="@dimen/px2dp"
            app:line_color="#f05b48"
            app:line_width="@dimen/px6dp"
            app:out_distance="@dimen/px10dp"
            app:out_ring_color="#75777a"
            app:out_ring_width="@dimen/px2dp"
            app:target_bottom_ring_color="#303438"
            app:target_ring_color="#f05b48"
            app:target_ring_width="@dimen/px64dp"
            app:wraper_center_ring_color="#35383c"
            app:wraper_center_ring_width="@dimen/px12dp" />
    

    在Activity中设置价格

    yearCostView.setMoney(135,270);//左侧为当前金额,右侧为总金额
    

    相关文章

      网友评论

        本文标题:年费比例控件

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