Android鬼点子 CircleProgressView

尹雅健
2023-12-01

分享一个最近在项目中用到的一个视图,具体的效果如下图:

打包赠送一个带光晕的按钮效果。

但是因为时间比较紧,这两个控件封装的不是很好,使用的时候需要修改一些代码中的参数(代码中有详细的comment,改起来还是很方便的……)

首先是上面的大圈圈。

package top.greendami.circleprogressview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;


/**
 * Created by zhaopy on 2017/2/23.
 */

public class CircleProgressView extends View {

    private String title = "规范评价";//显示的文字
    private float progress = 0; //显示的进度
    private int mLayoutSize = 100;//整个控件的尺寸(方形)
    public int mColor;//主要颜色
    public int mColorBackground;
    public int mColorShadow;

    private float now = 0; //当前的进度
    public CircleProgressView(Context context) {
        super(context);
    }

    public CircleProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mColor = context.getResources().getColor(R.color.colorPrimary);
        mColorBackground = context.getResources().getColor(R.color.white);
        mColorShadow = context.getResources().getColor(R.color.shadow);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        mLayoutSize = Math.min(widthSpecSize,heightSpecSize);
        setMeasuredDimension(mLayoutSize, mLayoutSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Shader mShader = new RadialGradient(mLayoutSize/2 , mLayoutSize/2, mLayoutSize/2,new int[]{Color.BLACK ,Color.DKGRAY , Color.GRAY ,Color.WHITE }
                ,null,
                Shader.TileMode.REPEAT);


        //画阴影
        Paint paint3 = new Paint();
        paint3.setShader(mShader);
        canvas.drawCircle(mLayoutSize/2, mLayoutSize/2, mLayoutSize/2 * 0.99f, paint3);

        int centre = getWidth()/2; //获取圆心的x坐标
        float radius = mLayoutSize/2 * 0.95f; //圆环的半径


        //画白圆
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL); //设置空心
        radius = mLayoutSize/2 * 0.925f; //圆环的半径
        canvas.drawCircle(centre, centre, radius, paint); //画出圆环


        //画第一个扇形
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(mColor);
        paint.setStyle(Paint.Style.FILL); //

        float boder = mLayoutSize/2 - radius;
        RectF rectF = new RectF(boder, boder ,
                mLayoutSize - boder,  mLayoutSize - boder);
        canvas.drawArc(rectF,-90,360 * (now / 100),true,paint);
        //画第二个内心圆,如果想让线粗一点,把0.98f改小一点
        boder = boder * 1.2f;
        rectF = new RectF(boder, boder ,
                mLayoutSize - boder,  mLayoutSize - boder);
        paint.setColor(Color.WHITE);
        canvas.drawCircle(centre, centre, radius * 0.98f, paint); //画出圆

        //画顶头的小球,0.05f是小球的半径
        paint.setColor(mColor);

        float r = radius * 0.98f;
        canvas.drawCircle(r + (float)(r * Math.sin(Math.toRadians(360 * (now / 100)))) + boder,
                r + boder - (float)(r  * Math.cos(Math.toRadians(360 * (now / 100)))) ,
                radius * 0.05f , paint);

        String per = now + "%";

        //写文字,1.1f控制百分比字的Y轴位置

        //写百分比
        paint.measureText(per);
        paint.setColor(mColor);
        paint.setTextSize(mLayoutSize/5);//控制文字大小
        canvas.drawText(per,centre - paint.measureText(per)/2,centre - (paint.ascent()+ paint.descent()) * 1.1f ,paint);

        //写标题
        paint.setColor(Color.GRAY);
        paint.setTextSize(mLayoutSize/10);//控制文字大小
        canvas.drawText(title,centre - paint.measureText(title)/2,centre + (paint.ascent()+ paint.descent()) ,paint);

        if(now < progress - 1){
            now = now + 1 ;
            postInvalidate();
        }else if(now < progress){
            now = progress;
            postInvalidate();
        }
    }

    //外部回掉
   public void setProgress(float progress,boolean isAnim) {
        this.progress = progress;
        if(!isAnim){
            now = progress;
        }
        postInvalidate();
    }
}

复制代码

下面是按钮的drawable,这个按钮就是用一个drawable实现的,然后当作按钮的背景,实现的思路是画几个连续的圆形广韵,然后给按钮的主体背景(圆角矩形)加上padding。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!--画出背景的光晕 -->

    <item android:left="65dp">
        <shape android:shape="rectangle"
            >
            <gradient

                android:endColor="#00fffaf0"
                android:startColor="#8049c29d"
                android:type="radial"
                android:gradientRadius="100"/>
        </shape>
    </item>
    <item android:left="25dp">
        <shape android:shape="rectangle" >
            <gradient
                android:endColor="#00fffaf0"
                android:startColor="#8049c29d"
                android:type="radial"
                android:gradientRadius="100"/>
        </shape>
    </item>
    <item >
        <shape android:shape="rectangle" >
            <gradient
                android:endColor="#00fffaf0"
                android:startColor="#8049c29d"
                android:type="radial"
                android:gradientRadius="100"/>
        </shape>
    </item>

    <item android:right="25dp">
        <shape android:shape="rectangle" >
            <gradient
                android:endColor="#00fffaf0"
                android:startColor="#8049c29d"
                android:type="radial"
                android:gradientRadius="100"/>
        </shape>
    </item>

    <item android:right="65dp">
        <shape android:shape="rectangle" >
            <gradient
                android:endColor="#00fffaf0"
                android:startColor="#8049c29d"
                android:type="radial"
                android:gradientRadius="100"/>
        </shape>
    </item>

     <!-- 画出按钮-->
    <item android:bottom="10dp" android:right="10dp" android:left="10dp" android:top="10dp">
        <shape
            android:shape="rectangle"
            android:useLevel="false">
            <corners android:radius="30dp" />
            <solid android:color="@color/colorPrimary" />
        </shape>
    </item>



</layer-list>
复制代码

使用方法,我这里固定的按钮的大小,如果需要调整按钮大小的话,需要改变drawable中光晕的位置()和光晕的大小(android:gradientRadius="100")

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="@color/white"
    tools:context="top.greendami.circleprogressview.MainActivity">

    <top.greendami.circleprogressview.CircleProgressView
        android:id="@+id/cv"
        android:background="@color/white"
        android:layout_width="400dp"
        android:layout_height="400dp" />


    <Button
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        style="?android:attr/borderlessButtonStyle"
        android:textColor="@color/white"
        android:background="@drawable/green_button_normal"
        android:text="开始工作"
        android:layout_width="130dp"
        android:layout_height="65dp" />
</RelativeLayout>

复制代码

在Activity中设置进度


CircleProgressView CV = (CircleProgressView)findViewById(R.id.cv);

CV.setProgress(35.8f);
复制代码
 类似资料: