首页 > 编程语言 > android实现简单仪表盘效果
2021
07-17

android实现简单仪表盘效果

本文实例为大家分享了android实现简单仪表盘效果的具体代码,供大家参考,具体内容如下

实现这个效果:

中间的文字很好写,外层的进度条就需要自定义控件了,代码如下:

public class CirCleProgressBar extends View {

    private Paint circlePaint;
    private Paint textPaint;
    private int circleColor;//圆弧颜色
    private int circleBgColor;//圆弧背景颜色
    private float circleWidth;//圆弧宽度
    private float circleBgWidth;//圆弧背景宽度
    private int textColor;//字体颜色
    private float textSize;//字体大小
    private int totalAngle;//总角度
    private int startAngle;//开始角度
    private float currentProgress;//当前进度
    private float maxProgress;//最大进度
    private float section;//分段

    private float currentAngle;//当前角度
    private float lastAngle;
    private ValueAnimator progressAnimator;//圆弧动画
    private int duration = 1000;//动画时长
    private  boolean isDefaultText;//是否设置文字显示的值
    private  String mTextValue;//字体显示的值

    public CirCleProgressBar(Context context) {
        this(context, null);
    }

    public CirCleProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CirCleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        circlePaint = new Paint();
        textPaint = new Paint();
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CirCleProgressBar);
        circleColor = typedArray.getColor(R.styleable.CirCleProgressBar_circle_color, Color.RED);
        circleBgColor = typedArray.getColor(R.styleable.CirCleProgressBar_circle_bg_color, Color.YELLOW);
        circleWidth = typedArray.getDimension(R.styleable.CirCleProgressBar_circle_width, 2);
        circleBgWidth = typedArray.getDimension(R.styleable.CirCleProgressBar_circle_bg_width, 2);
        textColor = typedArray.getColor(R.styleable.CirCleProgressBar_text_color, Color.BLUE);
        textSize = typedArray.getDimension(R.styleable.CirCleProgressBar_text_size, 10);
        totalAngle = typedArray.getInteger(R.styleable.CirCleProgressBar_total_angle, 360);
        startAngle = typedArray.getInteger(R.styleable.CirCleProgressBar_start_angle, 0);
        currentProgress = typedArray.getFloat(R.styleable.CirCleProgressBar_current_progress, 0);
        maxProgress = typedArray.getFloat(R.styleable.CirCleProgressBar_max_progress, 100);
        setCurrentProgress(currentProgress);
        setMaxProgress(maxProgress);
        //
        typedArray.recycle();
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**
         * 画最外层的大圆环
         */
        int centre = getWidth() / 2; // 获取圆心的x坐标
        int radius = (int) (centre - circleWidth / 2) - 2; // 圆环的半径
        circlePaint.setColor(circleBgColor);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setAntiAlias(true);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);// 圆头
        circlePaint.setStrokeWidth(circleBgWidth);
        RectF oval = new RectF(centre - radius - 1, centre - radius - 1, centre + radius + 1, centre + radius + 1); // 用于定义的圆弧的形状和大小的界限
        //背景圆
        canvas.drawArc(oval, startAngle, totalAngle, false, circlePaint);
        //数据圆
        circlePaint.setStrokeWidth(circleWidth);
        circlePaint.setColor(circleColor);
        canvas.drawArc(oval, startAngle, currentAngle, false, circlePaint);
        //
        textPaint.setAntiAlias(true);
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        float textWidth = textPaint.measureText((int) currentProgress + "");
        if(!isDefaultText) {
            canvas.drawText(String.valueOf((int)currentProgress), centre - textWidth / 2, centre + textSize / 2, textPaint);
        }else {
            canvas.drawText(mTextValue, centre - textWidth / 2, centre + textSize / 2, textPaint);
        }
        //
        invalidate();
    }

    public float getMaxProgress(){
        return maxProgress;
    }

    public void setMaxProgress(float maxProgress){
        if(maxProgress < 0){
            throw new IllegalArgumentException("max not less than 0");
        }
        this.maxProgress = maxProgress;
        section = totalAngle / maxProgress;
    }

    public void setAnimationDuration(int duration){
        this.duration = duration;
    }

    public void setCurrentProgress(float progress){
        if(progress >= 0){
            this.currentProgress = progress;
            if(progress > maxProgress){
                progress = maxProgress;
            }
            lastAngle = currentAngle;
            setAnimation(lastAngle, progress * section, duration);
        }

    }

    private void setAnimation(float last, float current, int duration){
        progressAnimator = ValueAnimator.ofFloat(last, current);
        progressAnimator.setDuration(duration);
        progressAnimator.setTarget(currentAngle);
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                currentAngle = (float) valueAnimator.getAnimatedValue();
                currentProgress = currentAngle / section;
            }
        });
        progressAnimator.start();
    }

    public int getCircleColor() {
        return circleColor;
    }

    public void setCircleColor(int circleColor) {
        this.circleColor = circleColor;
    }

    public int getCircleBgColor() {
        return circleBgColor;
    }

    public void setCircleBgColor(int circleBgColor) {
        this.circleBgColor = circleBgColor;
    }

    public float getCircleWidth() {
        return circleWidth;
    }

    public void setCircleWidth(float circleWidth) {
        this.circleWidth = circleWidth;
    }

    public float getCircleBgWidth() {
        return circleBgWidth;
    }

    public void setCircleBgWidth(float circleBgWidth) {
        this.circleBgWidth = circleBgWidth;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public float getTextSize() {
        return textSize;
    }

    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    /**
     * @param isText 为true,自定义设置字体显示
     * @param text
     */
    public  void setText(boolean isText,String text){
        isDefaultText = isText;
        mTextValue = text;
    }
}

需要在attrs中添加:

<declare-styleable name="CirCleProgressBar">
        <attr name="circle_color" format="color"/>
        <attr name="circle_bg_color" format="color"/>
        <attr name="circle_width" format="dimension"/>
        <attr name="circle_bg_width" format="dimension"/>
        <attr name="text_color" format="color"/>
        <attr name="text_size" format="dimension"/>
        <attr name="total_angle" format="integer"/>
        <attr name="start_angle" format="integer"/>
        <attr name="current_progress" format="float"/>
        <attr name="max_progress" format="float"/>
</declare-styleable>

使用方法:

在布局文件中直接引用

<com.fm.newcinema.view.CirCleProgressBar
                android:id="@+id/cc_cinema_sentiment"
                android:layout_width="139dp"
                android:layout_height="99dp"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="8dp"
                app:circle_bg_color="@color/gray_line_ff"
                app:circle_bg_width="10dp"
                app:circle_color="@color/main_blue"
                app:circle_width="10dp"
                app:max_progress="100"
                app:start_angle="160"
                app:text_color="@color/white_ff"
                app:text_size="@dimen/size_30px"
                app:total_angle="221"/>

其中app:circle_bg_color表示进度条底层的颜色,app:circle_color表示进度条上层的颜色,app:circle_bg_width表示进度条底层的宽度,app:circle_width表示进度条上层的宽度,app:max_progress="100"表示进度条最大进度是100,app:start_angle表示开始的角度,就是进度条从哪个角度开始画,如下图所示

app:total_angle表示整个进度条所需的角度.
在代码中设置旋转的角度,图中进度为30%,由于在布局文件中设置的最大进度是100`app:max_progress="100",所以进行如下设置peocess.setCurrentProgress(30f)
默认情况下,进度条中间显示进度条的值,如果需要自己写值的画,调用这个方法:process.setText(true, "中间的字");

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。

编程技巧