android自定义柱形图绘制

思路:

1、定义一个布局容器用来做画布;

2、定义一个 View类 用 Paint 将要绘制的图像都绘制出来;

3、在调用的类里定义一个方法插入需要的数据以此绘图。


视图效果:

点击按钮时调用绘图方法将图绘制出来,也可以直接在界面上绘制



详解:

1、定义一个布局容器用来做画布;

我的布局定义在了 activity_column.xml 里面,如下:

<Button
    android:id="@+id/start"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="开始绘制柱状图"/>

<!--柱状图绘制的地方-->
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:orientation="vertical"
    android:background="#00000000"
    android:paddingEnd="15dp"
    android:paddingStart="15dp">
    <LinearLayout
        android:id="@+id/column"
        android:background="#00000000"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">
    </LinearLayout>
</RelativeLayout>

在这个布局中,将要绘制的柱形图会根据 id--column 绘制在 LinearLyout 里面


2、定义一个 View类 用 Paint 将要绘制的图像都绘制出来;

这里才是重点,这里需要自己获取布局的大小坐标,根据画布坐标绘制图形

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.view.View;

import java.util.List;

/**
 * Created by Administrator on 2018/3/14 0014.
 * 柱状图的绘制
 */

public class ColumnView extends View {

    private String[] transverse;    //横列的刻度值数组
    private String[] vertical;      //竖列的刻度值数组
    private List<Integer> colors;    //画笔颜色集合
    private int[] high;           //柱状图高度数值数组

    //整个画布的宽、高
    private int width;
    private int height;

    // X,Y轴的单位长度 (类似网格切割)
    private int xScale;
    private int yScale;

    // 默认边距
    private int margin = 20;
    // 距离左边偏移量
    private int marginX = 30;
    // 原点坐标
    private int xPoint;
    private int yPoint;

    // 画笔
    private Paint paintAxes;            //画轴
    private Paint paintCoordinate;      //画坐标(文字或数值)
    private Paint paintRectF;           //画矩形

    public ColumnView(Context context) {
        super(context);
    }

    //在构造方法中传入横列的刻度值数组、竖列的刻度值数组、画笔颜色集合、柱状图高度数值数组
    public ColumnView(Context context, String[] transverse, String[] vertical, List<Integer> colors, int[] high) {
        super(context);
        this.transverse = transverse;
        this.vertical = vertical;
        this.colors = colors;
        this.high = high;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        init();
        drawAxesLine(canvas, paintAxes);            //绘制横、竖轴
        drawCoordinate(canvas, paintCoordinate);   //绘制坐标(文字或数值)
        drawColumn(canvas, paintRectF, high);//画柱形图
    }

    //初始化数据值和画笔
    public void init(){
        //计算原点坐标和单位长度
        xPoint = margin + marginX;
        yPoint = this.getHeight() - margin;
        xScale = (this.getWidth() - 2 * margin - marginX) / (transverse.length - 1);
        yScale = (this.getHeight() - 2 * margin) / (vertical.length - 1);

        paintAxes = new Paint();     //画轴(横轴和竖轴)
        paintAxes.setStyle(Paint.Style.STROKE);
        paintAxes.setAntiAlias(true);
        paintAxes.setDither(true);
        paintAxes.setColor(ContextCompat.getColor(getContext(), colors.get(0)));
        paintAxes.setStrokeWidth(1);

        paintCoordinate = new Paint(Paint.ANTI_ALIAS_FLAG);    //画坐标(文字或数值)
        paintCoordinate.setColor(ContextCompat.getColor(getContext(), colors.get(1)));
        paintCoordinate.setTextSize(22f);

        paintRectF = new Paint();       //画矩形
        paintRectF.setColor(ContextCompat.getColor(getContext(), colors.get(2)));
        paintRectF.setStyle(Paint.Style.FILL);
        paintRectF.setDither(true);
        paintRectF.setAntiAlias(true);
    }



    // 绘制坐标轴
    private void drawAxesLine(Canvas canvas, Paint paint) {
        // 画 X 轴
        canvas.drawLine(xPoint + 20, yPoint - 20, this.getWidth() - margin / 6 + 20, yPoint - 20, paint);
        // 画 Y 轴
        canvas.drawLine(xPoint + 20, yPoint - 20, xPoint + 20, margin / 6 - 20, paint);
    }

    // 绘制坐标刻度 (可以根据自己需要进行微调)
    private void drawCoordinate(Canvas canvas, Paint paint) {
        // X轴坐标
        for (int i = 0; i <= (transverse.length - 1); i++) {
            paint.setTextAlign(Paint.Align.CENTER);
            int startX = xPoint + i * xScale;
            canvas.drawText(transverse[i], startX - 10, this.getHeight() - margin / 6, paint);
        }

        // Y轴坐标
        for (int i = 0; i <= (vertical.length - 1); i++) {
            paint.setTextAlign(Paint.Align.LEFT);
            int startY = yPoint - i * yScale;
            int offsetX;
            switch (vertical[i].length()) {
                case 1:
                    offsetX = 28;
                    break;
                case 2:
                    offsetX = 20;
                    break;
                case 3:
                    offsetX = 12;
                    break;
                case 4:
                    offsetX = 5;
                    break;
                default:
                    offsetX = 0;
                    break;
            }
            int offsetY;
            if (i == 0) {
                offsetY = 0;
            } else {
                offsetY = margin / 5;
            }
            canvas.drawText(vertical[i], margin / 4 + offsetX - 10, startY + offsetY - 5, paint);
        }
    }


    // 绘制单柱形
    private void drawColumn(Canvas canvas, Paint paint, int data[]) {
        for (int i = 1; i <= (transverse.length - 1); i++) {
            int startX = xPoint + i * xScale;
            RectF rect = new RectF(startX - 20, toY(data[i - 1]), startX + 5, this.getHeight() - margin*2);
            canvas.drawRect(rect, paint);
        }
    }

    //数据按比例转换坐标(可以根据需要自己设置转换比例)
    private float toY(int num) {
        float y;
        try {
            float a = (float) num / 100.0f;
            y = yPoint - a * yScale;
        } catch (Exception e) {
            return 0;
        }
        return y;
    }
}

在这个 ColumnView 类中,需要继承 View ;

在 ColumnView 的构造方法中传入绘图所需要的一些数据,包括 :

在构造方法中传入横列的刻度值数组、竖列的刻度值数组、画笔颜色集合、柱状图高度数值数组

接下来就是在 onDraw()中绘制图形了:

首先:在 init() 中初始化数值、定义画笔样式等

接下来:drawAxesLine(Canvas canvas, Paint paint)  定义画 X、Y 轴的方法

     drawCoordinate(Canvas canvas, Paint paint) 画坐标(横竖的文字)

     drawColumn(Canvas canvas, Paint paint, int data[])画柱状图

最后:调用这些方法

当然了,有的时候传进来的数值与画布里的数值不同,就需要用 toY() 方法 自定义的按比例转换


3、在调用的类里定义一个方法插入需要的数据以此绘图。

上面将关键的事都做完了,接下来就是调用了

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import com.win.customview.R;

import java.util.ArrayList;
import java.util.List;

//自定义绘制柱状图
public class ColumnActivity extends AppCompatActivity {

    private Button start;//开始绘制
    private LinearLayout column;//柱状图绘制的地方
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_column);
        start = (Button)findViewById(R.id.start);
        column = (LinearLayout) findViewById(R.id.column);
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //这里调用绘制方法  (也可以直接调用显示的)
                barChart();
            }
        });
    }

    // 初始化柱状图数据(可以根据自己需要插入数据)
    private void barChart() {
        //第一个为空,它需要占一个位置
        String[] transverse = {"","周一","周二","周三","周四","周五","周六","周日"};
        String[] vertical = {"0", "2h", "4h", "8h", "10h"};
        //这里的数据是根据你横列有几个来设的,如上面的横列星期有周一到周日,所以这里设置七个数据
        int[] data = {420 , 380, 340, 300, 260, 220, 180};
        //这里的颜色就对应线条、文字和柱状图(可以根据自己的需要到color里设置)
        List<Integer> color = new ArrayList<>();
        color.add(R.color.colorAccent);
        color.add(R.color.colorPrimary);
        color.add(R.color.green);
        column.addView(new ColumnView(this, transverse, vertical, color, data));
    }
}

这里可以看到,点击按钮后,主要是调用了 barChart() 方法

在这个方法中我们向 ColumnView 的构造方法中传入了四个数组,

用 addView() 方法将绘制的图形放入了 coiumn 中(上面定义的一个布局)

这样就大功告成了


提示:如果需要绘制其他的图形也可以根据这个模式一步步的添加图形,最后达到想要的效果

图形的颜色可以自己随意更改!!!


源码:https://github.com/iscopy/CustomView

column 包中











猜你喜欢

转载自blog.csdn.net/weixin_41454168/article/details/79553303
今日推荐