Android 自定义view绘制圆环占比动画_Restart。的博客-程序员宅基地

技术标签: 自定  view  

对于自定义view,应该对于一个程序员来说并不是很陌生。自定义view主要分为三部分onMeasure测量、onLayout摆放和onDraw绘制。好了,言归正传,说一下怎样绘制圆环占比动画吧!!!

 

第一步:首先先自定义一个类,这里面主要绘制圆环的形状等一些状态。

public class CircleProgressBar extends View {
    /**
     * 绘制百分比的圆,一共有四部分,分别是里面的文字、背景圆、默认圆环、开始绘制的圆环;
     * 思路:首先需要四支画笔, 设置画笔对应的属性等;
     */
    private Paint roundColorPaint;//外圆画笔
    private Paint mCirclePaint;//中心园的画笔
    private Paint mTextPaint;//文字的画笔
    private Paint mArcPaint;//外圆环的画笔
    private int mCircleX;//设置圆心x坐标
    private int mCircleY;//设置圆心y坐标
    private float mCurrentAngle;//当前角度
    private RectF mArcRectF;//画中心园的外接矩形,用来画圆环用
    private float mStartSweepValue;//圆环开始角度
    private float mTargetPercent;//设置目标的百分比(也就是后台返回的数据)
    private float mCurrentPercent;//当前百分比

    private int mRadius;//圆的半径
    private int mCircleBackground;//中间圆的背景颜色
    private int mRingColor;//外圆环的颜色  第二次画圆的颜色
    private int roundColor; //外圆环的颜色 第一次画圆的颜色
    private int mTextSize;//字体大小
    private int mTextColor;//字体颜色
    public CircleProgressBar(Context context) {
        super(context);
        //初始化数据
        init(context);
    }
    public CircleProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 自定义属性,attr
        // 使用TypedArray
        //自定义属性 values/attr
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PercentageRing);
        //中间圆的背景颜色  默认 - 白色
        mCircleBackground = typedArray.getColor(R.styleable.PercentageRing_circleBackground, 0xff000000);
        //外圆环的颜色  默认 - 灰色
        roundColor = typedArray.getColor(R.styleable.PercentageRing_circleColor, 0xfff5f5f5);
        //外圆环的颜色  动态画圆 - 默认-红色
        mRingColor = typedArray.getColor(R.styleable.PercentageRing_ringColor, 0xfff5f5f5);
        //中间圆的半径 默认为80
        mRadius = typedArray.getInt(R.styleable.PercentageRing_radius, 80);
        //字体颜色 默认 - 灰色
        mTextColor = typedArray.getColor(R.styleable.PercentageRing_textColor, 0xff999999);
        //最后一定要调用这个 释放掉TypedArray
        typedArray.recycle();
        //初始化数据
        init(context);
    }

    public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

//    public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
//        super(context, attrs, defStyleAttr, defStyleRes);
//        init(context);
//    }
    private void init(Context context){
        //圆环开始角度 -90° 正北方向
        mStartSweepValue = -90;
        //当前角度
        mCurrentAngle = 0;
        //当前百分比
        mCurrentPercent = 0;
        //设置中心园的画笔
        mCirclePaint = new Paint();
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setColor(mCircleBackground);
        mCirclePaint.setStyle(Paint.Style.FILL);
        //设置文字的画笔
        mTextPaint = new Paint();
        mTextPaint.setColor(mTextColor);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setStrokeWidth((float) (0.025*mRadius));
        mTextPaint.setTextSize(mRadius/2);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        //设置外圆环的画笔
        mArcPaint = new Paint();
        roundColorPaint = new Paint();
        roundColorPaint.setColor(roundColor);
        mArcPaint.setAntiAlias(true);
        mArcPaint.setColor(mRingColor);
        mArcPaint.setStyle(Paint.Style.STROKE);
        mArcPaint.setStrokeWidth((float) (0.075*mRadius));
        //获得文字的字号 因为要设置文字在圆的中心位置
        mTextSize = (int) mTextPaint.getTextSize();
    }
    //主要是测量wrap_content时候的宽和高,因为宽高一样,只需要测量一次宽即可,高等于宽
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measure(widthMeasureSpec), measure(widthMeasureSpec));
        //设置圆心坐标
        mCircleX = getMeasuredWidth()/2;
        mCircleY = getMeasuredHeight()/2;
        //如果半径大于圆心横坐标,需要手动缩小半径的值,否则就画到外面去了
        if (mRadius>mCircleX) {
            //设置半径大小为圆心横坐标到原点的距离
            mRadius = mCircleX;
            mRadius = (int) (mCircleX-0.075*mRadius);
            //因为半径改变了,所以要重新设置一下字体宽度
            mTextPaint.setStrokeWidth((float) (0.025*mRadius));
            //重新设置字号
            mTextPaint.setTextSize(mRadius/2);
            //重新设置外圆环宽度
            mArcPaint.setStrokeWidth((float) (0.075*mRadius));
            //重新获得字号大小
            mTextSize = (int) mTextPaint.getTextSize();
        }
        //画中心园的外接矩形,用来画圆环用
        mArcRectF = new RectF(mCircleX-mRadius, mCircleY-mRadius, mCircleX+mRadius, mCircleY+mRadius);
    }

    //当wrap_content的时候,view的大小根据半径大小改变,但最大不会超过屏幕
    private int measure(int measureSpec){
        int result=0;
        //1、先获取测量模式 和 测量大小
        //2、如果测量模式是MatchParent 或者精确值,则宽为测量的宽
        //3、如果测量模式是WrapContent ,则宽为 直径值 与 测量宽中的较小值;否则当直径大于测量宽时,会绘制到屏幕之外;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        }else {
            result =(int) (1.075*mRadius*2);
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
    //开始画中间圆、文字和外圆环
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //画中间圆
            canvas.drawCircle(mCircleX, mCircleY, mRadius, mCirclePaint);
            //画圆环
        roundColorPaint.setStyle(Paint.Style.STROKE);
        //设置外圆环的宽度(默认灰色的圆环)
        roundColorPaint.setStrokeWidth((float) (0.075*mRadius));
        canvas.drawCircle(mCircleX, mCircleY, mRadius, roundColorPaint);
        //动态绘制红色的圆环
        canvas.drawArc(mArcRectF, mStartSweepValue ,mCurrentAngle, false, mArcPaint);
        //画文字 -  此处可以注销(原因:不能绘制有小数的百分比,例如:1.4%   如果是5%、12%这些可以不用注销下面代码),自定义布局将获取的值写在Textview上,
        //再使用下面的setTargetPercent方法获取数据动态画圆
        //canvas.drawText(String.valueOf(mCurrentPercent)+"%", mCircleX, mCircleY+mTextSize/4, mTextPaint);
        //判断当前百分比是否小于设置目标的百分比
        if (mCurrentPercent<mTargetPercent) {
            //当前百分比+1
            mCurrentPercent+=1;
            //当前角度+360
            mCurrentAngle+=3.6;
            //每10ms重画一次
            postInvalidateDelayed(10);
        }
    }
    //设置目标的百分比
    public void setTargetPercent(float percent){
        this.mTargetPercent = percent;
    }
}

这个可以根据自己的需求来绘制自己喜欢的图形,上面的就是绘制出的自定义view的形状。

 

第二步:现在开始在activity中进行视图的绘制。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.ky.circleprogressbar.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="40dp"
        android:orientation="horizontal"
        >

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <com.ky.circleprogressbar.CircleProgressBar
                android:id="@+id/recommend_progressBar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:circleBackground="#00000000"
                android:layout_centerHorizontal="true"
                app:ringColor="#ffea4745"
                app:textColor="#ff999999"/>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_centerHorizontal="true"
                android:gravity="center"
                android:orientation="horizontal"
                android:visibility="visible">

                <TextView
                    android:id="@+id/recommend_rate_circle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text=""
                    android:textColor="#ff999999"
                    android:textSize="14.0sp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="%"
                    android:textColor="#ff999999"
                    android:textSize="12.0sp" />
            </LinearLayout>
        </RelativeLayout>
    </LinearLayout>
</LinearLayout>

同时,这个也是,也可以根据自己的需求绘制。

 

第三步:不用说就是在activity中去调用了,那么怎样去调用呢,其实很简单。

    private CircleProgressBar recommend_progressBar;//circle百分比
    private TextView recommend_rate_circle;//百分比利率

    private float aFloat = 75.8f;
    private Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recommend_progressBar = (CircleProgressBar) findViewById(R.id.recommend_progressBar);
        recommend_rate_circle = (TextView) findViewById(R.id.recommend_rate_circle);
        recommend_rate_circle.setText(String.valueOf(aFloat));//百分比利率
        recommend_progressBar.setTargetPercent(aFloat);//circle百分比
    }

是不是很简单呢?基本上自定义view绘制的流程就是这样,其实很简单的,主要是自己有思路。

好了今天就介绍到这里了,有问题的地方可以提出更正!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43049358/article/details/88183586

智能推荐

决策树实现预测是否购买点电脑_雍珑庚的博客-程序员宅基地

Python机器学习的库:scikit-learn简单高效的数据挖掘和机器学习分析对所有用户开放,根据不同需求高度可重用性基于Numpy, SciPy和matplotlib(如果大家需要关于数据分析方面的笔记,可查看公众号以前的文章,有什么好的学习经验或者技术可与作者取得联系,加入[码龙社]技术交流群,一起学习,共同进步)开源,商用级别:获得 BSD许可这里就用上一篇文章的案...

Kerberos认证模型(c语言实现)_kerberos代码_一个路过的Developer的博客-程序员宅基地

Kerberos认证模型原理概述Kerberos是一种计算机网络认证协议,它允许某实体在非安全网络环境下通信,向另一个实体以一种安全的方式证明自己的身份。它也指由麻省理工实现此协议,并发布的一套免费软件。它的设计主要针对客户-服务器模型,并提供了一系列交互认证——用户和服务器都能验证对方的身份。Kerberos协议可以保护网络实体免受窃听和重复攻击。Kerberos协议基于对称密码学,并需要一个值得信赖的第三方。Kerberos协议的扩展可以为认证的某些阶段提供公钥密码学支持。认证流程首先,用户使

决策树学习——基本原理,详细计算过程,预剪枝,后剪枝的计算方式以及思想,非常全面!!!_一只勤奋爱思考的猪的博客-程序员宅基地

【机器学习速成宝典】模型篇06决策树【ID3、C4.5、CART】(Python版)维基百科——维基百科,比较权威,多看看,顺便可以学学英语!! min_samples_split(分类所需最小样本数)与min_samples_leaf(叶节点最小样本数)区别!! max_leaf_nodes:最大叶节点数! 参考知乎:机器学习各种算法怎么调参? 看官方文档:class BaseD...

c语言--static和extern关键字_齐天大圣徐的博客-程序员宅基地

对于程序员,一般来说,我们可以简单的理解为内存分为三个部分:静态区,栈,堆。很多书没有把把堆和栈解释清楚,导致初学者总是分不清楚。其实堆栈就是栈,而不是堆。堆的英文是heap;栈的英文是stack,也翻译为堆栈。堆和栈都有自己的特性,这里先不做讨论。具体可参考http://blog.csdn.net/tigerjibo/article/details/7423728静态区:保存自动全局变量和stat

计算任意多边形的面积_行列式求任意多边形面积_ATM006的博客-程序员宅基地

以三角形为例设A(x1,y1),B(x2,y2),C(x3,y3) 由A-->B-->C-->A 按逆时针方向转。 设三角形的面积为S 则S=(1/2)*(下面行列式) |x1 y1 1| |x2 y2 1| |x3 y3 1| S=(1/2)*(x1y2*1+x2y3*1+x3y1*1-x1y3*1-x2y1*1-x3y2*1) 即用三角形的三个顶点坐标求其面积的公式为: S=(1/2)

Directed Graph Model_Rainbow6174的博客-程序员宅基地

The Directed Graph ModelA directed graph G consists of a set of vertices V and an edge set E of ordered pairs of vertices. For our purposes, each vertex corresponds to an artist. If (Y,X)∈E(Y,X) \in E(Y,X)∈E then there is an arrow pointing from YYY to XXX

随便推点

手机安装Charles证书后,抓取的请求依然为unknown(已解决)_测试小菜鸟_Grious的博客-程序员宅基地

问题:下载安装好证书后,请求依然如下图:解决办法:Proxy-&amp;gt;SSL Proxying Settings   进行如下设置:     

《Unix网络编程》卷1:套接字联网API(第3版):名字与地址互换、IPv4和IPv6互操作性_不才Jerry的博客-程序员宅基地

全书共31章+附录。计划安排:吃透这本书,一天三章+源码,并实测代码做当天笔记,CSDN见。时间安排:计划时间1.5个月 == 6个周末 == 12天。2017.08.05    第01-03章:TCP/IP简介、传输层、套接字编程简介2017.08.06    第04-06章:基本TCP编程、TCP客户端/服务器程序、I/O复用2017.08.12    第07-09章:

高德地图集成之基础定位_setmylocationstyle_VipPeterGee的博客-程序员宅基地

1、高德官网注册开发者账号并申请Ak2、下载响应的jar包和so文件,放到app下的libs文件夹3、build.gradle中配置sourceSets4、Manifest配置权限和service以及申请的Ak

Pandas 第三部分_weixin_30635053的博客-程序员宅基地

1 import numpy as np 2 import pandas as pd 3 4 df = pd.read_excel("d:/test.xlsx") 5 #数据重塑和轴向旋转 6 if 0: 7 #1,层次化索引 8 if 0: 9 #层次化索引是pandas 的一项重要功能...

shell脚本检查磁盘空间使用情况_shell脚本测试出系统挂载的使用量_pureluckyfish的博客-程序员宅基地

#!/bin/bash echo "" &gt; out.log cat ./service.ip.list | while read remote_ip do echo $remote_ip &gt;&gt; out.log ssh -f -n z[email protected]_ip "df -h" &gt;&gt; out.log don...

推荐文章

热门文章

相关标签