zoukankan      html  css  js  c++  java
  • Android中自定义环形图

    如图:

    自定义view

    package com.riverlet.ringview;
    
    import android.animation.ObjectAnimator;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    import android.view.animation.AccelerateInterpolator;
    
    
    
    public class AnnularChartView extends View {
    
        /**
         * 默认颜色
         */
        private static final int[] DEFAULT_COLOR = new int[]{0xff82B8FF, 0xffFF7F78, 0xffFFAE72, 0xff74D1B1, 0xffC38AFC};
        /**
         * 圆环半径,以内环算
         */
        private int innerRadius;
        /**
         * 圆环厚度
         */
        private int ringWidth;
        /**
         * 画笔数组
         */
        private Paint[] paints;
        /**
         * 画笔数组对应的颜色
         */
        private int[] colors = DEFAULT_COLOR;
        /**
         * 圆环圆心x坐标
         */
        private int centerX;
        /**
         * 圆环圆心y坐标
         */
        private int centerY;
        /**
         * 圆环范围
         */
        private RectF oval;
        /**
         * 每个数据对应的角度
         */
        private int[] angles;
        /**
         * 数据
         */
        private float[] datas;
        /**
         * 动画用的进度
         */
        private float progress;
        /**
         * 动画
         */
        private ObjectAnimator animator;
    
        public AnnularChartView(Context context) {
            this(context, null);
        }
    
        public AnnularChartView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public AnnularChartView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //动画
            initAnimator();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //矩形
            initRectF(getMeasuredWidth(), getMeasuredHeight());
        }
    
        /**
         * 计算圆环的范围
         *
         * @param w
         * @param h
         */
        private void initRectF(int w, int h) {
            if (w == 0 && h == 0) {
                return;
            }
            centerX = (int) ((float) w / 2);
            centerY = (int) ((float) h / 2);
            innerRadius = (int) ((float) w / 2 / 89 * 64);
            ringWidth = (int) ((float) w / 2 / 89 * 25);
            oval = new RectF(centerX - innerRadius, centerY - innerRadius, centerX + innerRadius, centerY + innerRadius);
        }
    
        /**
         * 初始化paint
         */
        private void initPaints() {
            if (datas == null) {
                angles = null;
            } else {
                float total = 0;
                for (float data : datas) {
                    total += data;
                }
                if (total <= 0) {
                    angles = null;
                } else {
                    angles = new int[datas.length];
                    int sumAngles = 0;
                    for (int i = 0; i < datas.length; i++) {
                        float angle;
                        if (i == datas.length - 1) {
                            angles[i] = 360 - sumAngles;
                            Log.v("setData", angles[i] + "");
                        } else {
                            angle = datas[i] / total * 360;
                            if (angle < 1) {
                                angles[i] = 1;
                            } else {
                                angles[i] = Math.round(angle);
                            }
                            sumAngles += angles[i];
                            Log.v("setData", angles[i] + "");
                        }
                    }
                }
            }
            if (angles != null) {
                //用于定义的圆弧的形状和大小的界限
                paints = new Paint[angles.length];
                for (int i = 0; i < angles.length; i++) {
                    Paint paint = new Paint();
                    paint.setColor(colors[i % colors.length]);
                    paint.setStyle(Paint.Style.STROKE);
                    paint.setStrokeWidth(25);
                    paint.setAntiAlias(true);
                    paints[i] = paint;
                }
            }
            animStart();
        }
    
        private void initAnimator() {
            progress = 0;
            animator = ObjectAnimator.ofFloat(this, "progress", 0f, 1.0f);
            animator.setDuration(800);
            animator.setInterpolator(new AccelerateInterpolator());
            animator.start();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (oval == null) {
                initRectF(getWidth(), getHeight());
            }
            int lastAngle = 0;
            int nums = angles == null ? 0 : angles.length;
            if (nums > 0) {
                for (int i = 0; i < nums; i++) {
                    if (i > 0) {
                        lastAngle = (int) (lastAngle + angles[i - 1] * progress);
                    }
                    paints[i].setStrokeWidth(ringWidth);
                    if (angles[i] > 0) {
                        canvas.drawArc(oval, 270 + lastAngle, (angles[i] + 1) * progress, false, paints[i]);
                    }
                }
            } else {
                Paint paint = new Paint();
                paint.setColor(0xffa0a0a0);
                paint.setStyle(Paint.Style.STROKE);
                paint.setStrokeWidth(ringWidth);
                paint.setAntiAlias(true);
                canvas.drawArc(oval, 270, 360 * progress + 1, false, paint);
            }
        }
    
        public float getProgress() {
            return progress;
        }
    
        public void setProgress(float progress) {
            this.progress = progress;
            invalidate();
        }
    
    
        /**
         * 开始动画
         */
        public void animStart() {
            if (animator.isStarted()) {
                animator.cancel();
            }
            animator.start();
        }
    
        public void setData(float[] datas) {
            this.datas = datas;
            initPaints();
        }
    
        public int[] getColors() {
            return colors;
        }
    
        public void setColors(int[] colors) {
            this.colors = colors;
        }
    
        public void setAnimator(ObjectAnimator animator) {
            this.animator = animator;
        }
    }
    

      

    布局

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout 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.riverlet.ringview.MainActivity">
    
        <com.riverlet.ringview.AnnularChartView
            android:id="@+id/annularChartView"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_marginTop="30dp"
            android:text="Hello World!"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/text_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:background="@drawable/bg"
            android:padding="5dp"
            android:text="100 : 100 : 100 : 100 : 100"
            android:textColor="#ffffff"
            android:textSize="25sp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/annularChartView" />
    
        <TextView
            android:id="@+id/text_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:background="@drawable/bg"
            android:padding="5dp"
            android:text="100 : 200 : 300 : 400 : 500"
            android:textColor="#ffffff"
            android:textSize="25sp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text_1" />
    
        <TextView
            android:id="@+id/text_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:background="@drawable/bg"
            android:padding="5dp"
            android:text="500 : 100 : 300 : 100 : 600"
            android:textColor="#ffffff"
            android:textSize="25sp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/text_2" />
    </android.support.constraint.ConstraintLayout>
    

      

    MainActivity中
    package com.riverlet.ringview;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        AnnularChartView annularChartView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            annularChartView = findViewById(R.id.annularChartView);
            findViewById(R.id.text_1).setOnClickListener(this);
            findViewById(R.id.text_2).setOnClickListener(this);
            findViewById(R.id.text_3).setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.text_1:
                    annularChartView.setData(new float[]{100f, 100f, 100f, 100f, 100f});
                    break;
                case R.id.text_2:
                    annularChartView.setData(new float[]{100f, 200f, 300f, 400f, 500f});
                    break;
                case R.id.text_3:
                    annularChartView.setData(new float[]{500f, 100f, 300f, 100f, 600f});
                    break;
            }
        }
    }
    

      完成

    参考于://https://www.jianshu.com/p/03f6751e4c99

  • 相关阅读:
    Linux下Java安装与配置
    HYSPLIT模式简介及在线平台使用
    HYSPLIT模式简介及单机版使用图文教程
    有关气象类资料数据下载网址
    Excel图表编程应用大全(2):图表编程基础
    当装系统时遇到“选中的磁盘采用GPT分区形式”
    SQL函数
    Centos6.7 Redis3.2.8的主从搭建
    Centos 6.7 中 Redis-3.2.8的安装
    Mysql innodb_buffer_pool_size的研究
  • 原文地址:https://www.cnblogs.com/changyiqiang/p/10893158.html
Copyright © 2011-2022 走看看