今天做项目需要用到简单的横向的柱状图,上网查了一下,没找到合适的框架,于是决定自己动手写一个自定义View,来实现三种柱状图。

        那么先看效果图

android 柱形图实现 app柱状图怎么设置_i++

横向的柱状图,只有柱子的比例和文字。


android 柱形图实现 app柱状图怎么设置_i++_02

纵向的柱状图,加上了坐标轴的绘制。






android 柱形图实现 app柱状图怎么设置_android_03



比例式柱状图,只接受长度为2的数组,会自己判断将长的置于背景。







那么我们看一下这个自定义View的代码:

package com.example.day09;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;

/**
 * Created by Administrator on 2016/11/3.
 */

public class Histogram extends View {
    private int[] nums;
    private String[] names;
    private int[] colors;
    private Context context;
    private int max = 0;
    private int type;
    private int wheretext;
    private int maxlong;
    private int j;
    private int width;
    private int kong;
    private boolean useAnimation;
    private Histogram v;

    public void setNames(String[] names) {
        this.names = names;
    }

    public void setMax(int max) {
        this.max = max;
    }

    public void setType(int type) {
        this.type = type;
    }

    public void setWheretext(int wheretext) {
        this.wheretext = wheretext;
    }

    public void setMaxlong(int maxlong) {
        this.maxlong = maxlong;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setKong(int kong) {
        this.kong = kong;
    }


    public void setUseAnimation(boolean useAnimation) {
        this.useAnimation = useAnimation;
    }


    public Histogram(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        v = this;
    }

    public Histogram(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        v = this;
    }

    public Histogram(Context context) {
        super(context);
        v = this;
        this.context = context;
    }

    /**
     * 初始化柱状图的方法
     *
     * @param nums      存放每个元素数量的数组
     * @param names     存放每个元素文字的数组
     * @param colors    存放每个元素使用的颜色的数组
     * @param type      定义柱状图的类型 1为横向,2为纵向,其余为比例
     * @param wheretext 定义柱状图文字的位置  (若横向)1为图前,2为图后,其余为无文字;(若纵向)1为图下,其余无文字
     * @param maxlong   柱状图的最大长度(px)
     * @param max       最大长度对应的数值
     * @param width     每条柱子的宽度
     * @param kong      柱子之间的空隙宽度
     */
    public void SetHistogram(int[] nums, String[] names, int[] colors, int type, int wheretext, int maxlong, int max, int width, int kong, boolean useAnimation) {
        this.colors = colors;
        this.names = names;
        this.nums = nums;
        this.type = type;
        this.wheretext = wheretext;
        this.maxlong = maxlong;
        this.max = max;
        j = maxlong / max;
        this.width = width;
        this.kong = kong;
        this.useAnimation = useAnimation;
    }

    public void SetHistogram(int[] nums, int[] colors, int type) {
        SetHistogram(nums, null, colors, type, 0, 800, 100, 50, 0, false);
    }

    public void SetHistogram(int[] nums, int[] colors) {
        SetHistogram(nums, colors, 1);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        switch (type) {
            case 1:
                DrawHeng(canvas, p);
                break;
            case 2:
                DrawShu(canvas, p);
                break;
            default:
                DrawBiLi(canvas, p);
                break;
        }

    }

    /**
     * 画横向比例柱状图
     *
     * @param canvas
     * @param p
     */
    private void DrawBiLi(Canvas canvas, Paint p) {
        int i, j;
        if (nums[0] > nums[1]) {
            i = 0;
            j = 1;
        } else {
            i = 1;
            j = 0;
        }
        int[] numss = new int[]{nums[i], nums[j]};
        int[] colorss = new int[]{colors[i], colors[j]};
        String[] namess = new String[]{names[i], names[j]};
        float bili = (0.0F + numss[0]) / (0.0F + numss[1]);
        switch (wheretext) {
            case 1:
                p.setColor(colorss[0]);
                canvas.drawRect(0, 0, maxlong, width, p);
                p.setColor(colorss[1]);
                canvas.drawRect(0, 0, maxlong / bili, width, p);
                //写字
                p.setColor(Color.WHITE);
                p.setTextSize(width - 10);
                p.setTextAlign(Paint.Align.LEFT);
                canvas.drawText(namess[0], 10, width, p);
                canvas.drawText(namess[1], maxlong / bili + 10, width, p);
                if (useAnimation) {
                    setAnimationHeng();
                }
                break;
            default:
                p.setColor(colorss[0]);
                canvas.drawRect(0, 0, maxlong, width, p);
                p.setColor(colorss[1]);
                canvas.drawRect(0, 0, maxlong / bili, width, p);
                if (useAnimation) {
                    setAnimationHeng();
                }
                break;
        }

    }

    /**
     * 画纵向柱状图
     *
     * @param canvas
     * @param p
     */
    private void DrawShu(Canvas canvas, Paint p) {
        switch (wheretext) {
            case 1:
                //画坐标轴
                p.setStrokeWidth(5);
                p.setColor(Color.BLACK);
                canvas.drawLine(30, maxlong, nums.length * (width + kong) + 150, maxlong, p);
                canvas.drawLine(nums.length * (width + kong) + 150, maxlong, nums.length * (width + kong) + 120, maxlong - 30, p);
                canvas.drawLine(nums.length * (width + kong) + 150, maxlong, nums.length * (width + kong) + 120, maxlong + 30, p);
                canvas.drawLine(30, maxlong, 30, 0, p);
                canvas.drawLine(30, 0, 0, 30, p);
                canvas.drawLine(30, 0, 60, 30, p);
                //画柱子
                for (int i = 0; i < nums.length; i++) {
                    p.setColor(colors[i]);
                    canvas.drawRect(60 + kong + (i * (kong + width)), maxlong - (j * nums[i]), 60 + kong + (i * (kong + width)) + width, maxlong, p);
                    p.setColor(Color.BLACK);
                    p.setTextSize(width - 10);
                    p.setTextAlign(Paint.Align.LEFT);
                    canvas.drawText(names[i], 60 + ((width + kong) * i) + width / 4, maxlong + width, p);
                }
                if (useAnimation) {
                    setAnimationShu();
                }
                break;

            default:
                //画坐标轴
                p.setStrokeWidth(5);
                p.setColor(Color.BLACK);
                canvas.drawLine(30, maxlong, nums.length * (width + kong) + 150, maxlong, p);
                canvas.drawLine(nums.length * (width + kong) + 150, maxlong, nums.length * (width + kong) + 120, maxlong - 30, p);
                canvas.drawLine(nums.length * (width + kong) + 150, maxlong, nums.length * (width + kong) + 120, maxlong + 30, p);
                canvas.drawLine(30, maxlong, 30, 0, p);
                canvas.drawLine(30, 0, 0, 30, p);
                canvas.drawLine(30, 0, 60, 30, p);
                //画柱子
                for (int i = 0; i < nums.length; i++) {
                    p.setColor(colors[i]);
                    canvas.drawRect(60 + kong + (i * (kong + width)), maxlong - (j * nums[i]), 60 + kong + (i * (kong + width)) + width, maxlong, p);
                }
                if (useAnimation) {
                    setAnimationShu();
                }
                break;
        }

    }

    /**
     * 画横向柱状图
     *
     * @param canvas
     * @param p
     */
    private void DrawHeng(Canvas canvas, Paint p) {
        switch (wheretext) {
            case 1:
                for (int i = 0; i < nums.length; i++) {
                    p.setColor(Color.BLACK);
                    p.setTextSize(width - 10);
                    p.setTextAlign(Paint.Align.RIGHT);
                    canvas.drawText(names[i], 80, width + width * i, p);
                    p.setColor(colors[i]);
                    canvas.drawRect(100, i * width + kong, 100 + nums[i] * j, width + i * width, p);
                    if (useAnimation) {
                        setAnimationHeng();
                    }
                }
                break;
            case 2:
                for (int i = 0; i < nums.length; i++) {

                    p.setColor(colors[i]);
                    canvas.drawRect(0, i * width + kong, nums[i] * j, width + i * width, p);
                    p.setColor(Color.BLACK);
                    p.setTextSize(width - 10);
                    p.setTextAlign(Paint.Align.LEFT);
                    canvas.drawText(names[i], nums[i] * j + 20, width + width * i, p);
                    if (useAnimation) {
                        setAnimationHeng();
                    }
                }
                break;
            default:
                for (int i = 0; i < nums.length; i++) {

                    p.setColor(colors[i]);
                    canvas.drawRect(0, i * width + kong, nums[i] * j, width + i * width, p);
                    if (useAnimation) {
                        setAnimationHeng();
                    }
                }
                break;
        }

    }

    /**
     * 设置动画(横向)
     */
    private void setAnimationHeng() {
        ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 1.0f, 1.0f, 1.0f
                , Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
        scaleAnimation.setDuration(1000);
        this.setAnimation(scaleAnimation);
        scaleAnimation.startNow();
    }

    /**
     * 设置动画(横向)
     */
    private void setAnimationShu() {
        ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f
                , Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
        scaleAnimation.setDuration(1000);
        this.setAnimation(scaleAnimation);
        scaleAnimation.startNow();
    }
}



其中,设置所有参数的方法为

/**
     * 初始化柱状图的方法
     *
     * @param nums      存放每个元素数量的数组
     * @param names     存放每个元素文字的数组
     * @param colors    存放每个元素使用的颜色的数组
     * @param type      定义柱状图的类型 1为横向,2为纵向,其余为比例
     * @param wheretext 定义柱状图文字的位置  (若横向)1为图前,2为图后,其余为无文字;(若纵向)1为图下,其余无文字
     * @param maxlong   柱状图的最大长度(px)
     * @param max       最大长度对应的数值
     * @param width     每条柱子的宽度
     * @param kong      柱子之间的空隙宽度
     */
    public void SetHistogram(int[] nums, String[] names, int[] colors, int type, int wheretext, int maxlong, int max, int width, int kong, boolean useAnimation) {
        this.colors = colors;
        this.names = names;
        this.nums = nums;
        this.type = type;
        this.wheretext = wheretext;
        this.maxlong = maxlong;
        this.max = max;
        j = maxlong / max;
        this.width = width;
        this.kong = kong;
        this.useAnimation = useAnimation;
    }

后面的代码都是根据这个方法传进来的参数做出相应的绘制,当然,大多数有用的属性也单独提供了Set方法;






接下来我们简单的试验一下一个纵向的柱状图,代码如下:

MainActivity:

package com.example.day09;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;

public class MainActivity extends Activity {
	Histogram histogram;
			int[] nums;
	int[] colors;
	String[] names;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		histogram= (Histogram) findViewById(R.id.imageId);
		nums=new int[]{55,24,64,35,100};
		colors=new int[]{Color.BLUE,Color.YELLOW,0Xffabcdef,Color.GREEN,Color.RED};
		names=new String[]{"A","B","C","D","E"};
		histogram.SetHistogram(nums,names,colors,2,1,1000,100,80,10,false);
		ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 1.0f, 1.0f, 1.0f
				, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f);
		scaleAnimation.setDuration(1000);
		histogram.setAnimation(scaleAnimation);
		scaleAnimation.startNow();
		scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {

			}

			@Override
			public void onAnimationEnd(Animation animation) {
				histogram.setVisibility(View.VISIBLE);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {

			}
		});
	}

	
	
	

}



布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    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"
    tools:context=".MainActivity">

    <com.example.day09.Histogram
        android:id="@+id/imageId"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:visibility="invisible" />

</RelativeLayout>

这样就做出了一个简单的柱状图了,截图效果:

android 柱形图实现 app柱状图怎么设置_android 柱形图实现_04