注释在代码中:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by wangliang on 0013/2016/9/13.
* 思路:每传递一次坐标名称则更新一次视图,坐标的传递采用动态计算的方法,当更改坐标轴名称的时候,所有视图清空进行重绘,柱状图显示数量由所传递的徐州的名称决定
*/
public class HistogramNoScrollView extends View {
private Context context;
private final String TAG = "HistogramNoScrollView";
private Integer defaultAxisColor = Color.BLACK;
private Integer defaultAxisWidth;
private List xAxisListNames;
private List yAxisListNames;
private List xAxisCoordinateList;//所有x轴基准点坐标
private List yAxisCoordinateList;//所有y轴基准点坐标
private List xAxisTextCoordinateList;//所有x轴文字坐标
private List yAxisTextCoordinateList;//所有y轴文字坐标
private List listAllNoAxisCoordinate;//除轴上坐标之外的其他柱状图的坐标
private Paint xAxisTextPaint;//x轴文字画笔
private Paint yAxisTextPaint;//y轴文字画笔
private Paint xAxisPaint;//x轴画笔
private Paint yAxisPaint;//y轴画笔
private Paint histogramPaint;//柱状图画笔
private Paint averageValuePaint;//平均值线
private Path averageValuePath;//平均值线
private Integer axisTextColor;
private Integer axisTextSize;
private Integer defaultBetweenXAxisAndTextSpace;
private Integer defaultBetweenYAxisAndTextSpace;
private int xCoordinateDistance;//x轴每段的宽度
private Double maxValue;//柱状图所能显示的最大值
private Double averageValue;//柱状图的平均值
private Map histogramValue;//柱状图所哟柱子的值
private float histogramShowFanWei;//柱状图所能显示的范围
private Boolean whetherShowXAxis;//是否显示y轴
private Boolean whetherShowYAxis;//是否显示x轴
private Boolean whetherShowAverageValue;//是否显示柱状图平均值
public HistogramNoScrollView(Context context) {
super(context);
initSetting(context,null);
}
public HistogramNoScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initSetting(context,null);
}
public HistogramNoScrollView(Context context, AttributeSet attrs, Integer defStyleAttr) {
super(context, attrs, defStyleAttr);
initSetting(context,defStyleAttr);
}
private void initSetting(Context context, Integer defStyleAttr) {
this.context = context;
defaultBetweenXAxisAndTextSpace = 0;
defaultBetweenYAxisAndTextSpace = 0;
defaultAxisColor = Color.BLACK;
defaultAxisWidth = context.getResources().getDimensionPixelOffset(R.dimen.common_dp_0_2);
axisTextColor = Color.RED;
axisTextSize = context.getResources().getDimensionPixelOffset(R.dimen.default_text_medium);
xAxisTextPaint = new Paint();
xAxisTextPaint.setTextSize(axisTextSize);
xAxisTextPaint.setColor(axisTextColor);
yAxisTextPaint = new Paint();
yAxisTextPaint.setTextSize(axisTextSize);
yAxisTextPaint.setColor(axisTextColor);
xAxisPaint = new Paint();
xAxisPaint.setColor(defaultAxisColor);
xAxisPaint.setStrokeWidth(defaultAxisWidth);
yAxisPaint = new Paint();
yAxisPaint.setColor(defaultAxisColor);
yAxisPaint.setStrokeWidth(defaultAxisWidth);
averageValuePaint = new Paint ( ) ;
averageValuePaint.setColor ( Color.BLACK ) ;
//设置画直线格式
averageValuePaint.setStyle ( Paint.Style.STROKE ) ;
/**设置虚线效果
* 里边的float数组的意思是:先画长度为3的实线,再间隔长度为2的空白,之后一直重复这个单元。
* 这个数组的长度只要大于等于2就行,你可以设置多个数值,产生不同效果,最后这个0指的是与起始位置的偏移量。
*/
averageValuePaint.setPathEffect ( new DashPathEffect( new float [ ] { 3, 2 }, 0 ) ) ;
}
/**
* 设置x轴坐标文字
* @param xAxisListNames
* @return
*/
public HistogramNoScrollView setXAxisNames(List xAxisListNames,boolean whetherShowXAxis){
this.xAxisListNames = xAxisListNames;
this.whetherShowXAxis = whetherShowXAxis;
return this;
}
/**
* 设置y轴坐标文字
* @param yAxisListNames
* @return
*/
public HistogramNoScrollView setYAxisNames(List yAxisListNames,boolean whetherShowYAxis){
this.yAxisListNames = yAxisListNames;
this.whetherShowYAxis = whetherShowYAxis;
return this;
}
/**
* 设置柱状图所要显示的最大值以及平均值
* @param maxValue 最大值
* @param averageValue 平均值
* @param whetherShowAverageValue 是否显示平均值线
* @return
*/
public HistogramNoScrollView setMaxValueAndAverageValue(double maxValue,double averageValue,boolean whetherShowAverageValue){
this.maxValue = maxValue;
this.averageValue = averageValue;
this.whetherShowAverageValue = whetherShowAverageValue;
return this;
}
public HistogramNoScrollView setHistogramValue(Map histogramValue){
this.histogramValue = histogramValue;
return this;
}
@Override
protected void onDraw(Canvas canvas) {
if(xAxisTextCoordinateList == null){
getXAxisTextCoordinateList();
}
if(xAxisCoordinateList == null){
getXAxisCoordinateList();
}
if(yAxisTextCoordinateList == null){
getYAxisTextCoordinateList();
}
if(yAxisCoordinateList == null){
getYAxisCoordinateList();
}
if(listAllNoAxisCoordinate == null){
getListAllNoAxisCoordinate();
}
/**
* 获取所要画的虚线的path
*/
if(averageValuePath == null && maxValue != null && averageValue != null){
histogramShowFanWei = getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace;
averageValuePath = new Path();
averageValuePath.moveTo(0, (float) (histogramShowFanWei - histogramShowFanWei * (averageValue / maxValue)));
averageValuePath.lineTo(getWidth() - defaultBetweenYAxisAndTextSpace, (float) (histogramShowFanWei - histogramShowFanWei * (averageValue / maxValue)));
}
/**
* 画x轴
*/
if(xAxisTextCoordinateList.size() > 0 && whetherShowXAxis) {
canvas.drawLine(getX() - defaultBetweenYAxisAndTextSpace,
getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace,
getWidth(),
getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace
, xAxisPaint);
}
/**
* 画y轴
*/
if(yAxisTextCoordinateList.size() > 0 && whetherShowYAxis) {
canvas.drawLine(getX() - defaultBetweenYAxisAndTextSpace,
0,
getX() - defaultBetweenYAxisAndTextSpace,
getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace
, xAxisPaint);
}
/**
* 画虚线,代表着平均值
*/
if(listAllNoAxisCoordinate.size() > 0 && whetherShowAverageValue){
canvas.drawPath(averageValuePath,averageValuePaint);
}
/**
* 绘制x轴上的坐标刻度文字
*/
for(int i = 0 ; i < xAxisTextCoordinateList.size() ; i++){
canvas.drawText(xAxisTextCoordinateList.get(i).getCoordinatename(),
xAxisTextCoordinateList.get(i).getxCoordinate(),
xAxisTextCoordinateList.get(i).getyCoordinate(),
xAxisTextPaint);
}
/**
* 绘制柱状图
*/
for(int i = 0 ; i < listAllNoAxisCoordinate.size() ; i++){
histogramPaint = new Paint();
histogramPaint.setColor(listAllNoAxisCoordinate.get(i).getColor());
canvas.drawRect(new Rect(Math.round(listAllNoAxisCoordinate.get(i).getxStartCoordinate())
,Math.round(listAllNoAxisCoordinate.get(i).getyStartCoordinate())
,Math.round(listAllNoAxisCoordinate.get(i).getxStopCoordinate())
,Math.round(listAllNoAxisCoordinate.get(i).getyStopCoordinate()))
,histogramPaint);
}
}
private Paint.FontMetrics fm;
/**
* 根据文字获得文字相对于x轴的坐标
* @param text
* @param xCoordinateDistance
* @return
*/
private float[] getXtextCoordinate(String text,float xCoordinateDistance){
float[] xy = new float[2];
fm = xAxisTextPaint.getFontMetrics();
float textWidth = xAxisTextPaint.measureText(text);
float textHeight = fm.descent - fm.ascent;
xy[0] = xCoordinateDistance - textWidth / 2;
xy[1] = getHeight();
return xy;
}
/**
* 获取x轴刻度文字坐标
*/
private void getXAxisTextCoordinateList(){
xAxisTextCoordinateList = new ArrayList<>();
if(xAxisListNames != null) {
xCoordinateDistance = getWidth() / (xAxisListNames.size() + 1);
for (int i = 0; i < xAxisListNames.size(); i++) {
float[] xtextCoordinate = getXtextCoordinate(xAxisListNames.get(i), xCoordinateDistance * (i + 1));
xAxisTextCoordinateList.add(new Coordinate(xtextCoordinate[0], xtextCoordinate[1], xAxisListNames.get(i)));
}
}
}
/**
* 获取x轴线坐标
*/
private void getXAxisCoordinateList(){
xAxisCoordinateList = new ArrayList<>();
if(xAxisListNames != null) {
fm = xAxisTextPaint.getFontMetrics();
float textHeight = fm.descent - fm.ascent;
xCoordinateDistance = getWidth() / (xAxisListNames.size() + 1);
for (int i = 0; i < xAxisListNames.size(); i++) {
xAxisCoordinateList.add(new Coordinate(getX() + xCoordinateDistance * (i + 1)
, getHeight() - textHeight, xAxisListNames.get(i)));
}
}
}
/**
* 获取y轴刻度文字坐标
*/
private void getYAxisTextCoordinateList(){
yAxisTextCoordinateList = new ArrayList<>();
}
/**
* 获取y轴线坐标
*/
private void getYAxisCoordinateList(){
yAxisCoordinateList = new ArrayList<>();
}
private void getListAllNoAxisCoordinate(){
listAllNoAxisCoordinate = new ArrayList<>();
histogramShowFanWei = getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace;
LineCoordinate lineCoordinate;
if(maxValue != null && xAxisListNames != null && xAxisCoordinateList != null){
for(int i = 0 ; i < xAxisListNames.size() ; i++){
lineCoordinate = new LineCoordinate();
lineCoordinate.setxStartCoordinate((float) (xAxisCoordinateList.get(i).getxCoordinate() - xCoordinateDistance * 0.45));
lineCoordinate.setyStartCoordinate((float) (xAxisCoordinateList.get(i).getyCoordinate() -
histogramShowFanWei * (histogramValue.get(xAxisListNames.get(i)) / maxValue)));
lineCoordinate.setxStopCoordinate((float) (xAxisCoordinateList.get(i).getxCoordinate() + xCoordinateDistance * 0.45));
lineCoordinate.setyStopCoordinate((float) (xAxisCoordinateList.get(i).getyCoordinate()));
lineCoordinate.setColor(Color.BLACK);
listAllNoAxisCoordinate.add(lineCoordinate);
}
}
}
}
调用方法:
List<String> list = new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
list.add("147");
list.add("258");
Map<String,Double> map = new HashMap<>();
map.put(list.get(0),10d);
map.put(list.get(1),15d);
map.put(list.get(3),7d);
((HistogramNoScrollView)findViewById(R.id.test1)).setXAxisNames(list,true);
((HistogramNoScrollView)findViewById(R.id.test1)).setMaxValueAndAverageValue(20,10,true);
((HistogramNoScrollView)findViewById(R.id.test1)).setHistogramValue(map);
坐标类参考:http://blog.csdn.net/cmwly/article/details/49951913