需求:
画一个圆角柱状图,显示12个月的数据,Y轴数据动态分割,如果是当前月,就画出当前月图片;点击柱状图变色,并显示虚线弹出当前月信息,滑动时弹框和虚线消失,柱状图刷新到最初。
1.HistogramRound
package com.broker.liming.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
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.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import com.broker.liming.R;
import com.broker.liming.bean.ChartData;
import com.broker.liming.utils.ArithUtil;
import com.broker.liming.utils.LogUtil2;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
/**
* @author chenhuirong
* @Date 2018/12/10
* @Description zhu
*/
public class HistogramRound extends ChartYdate {
private int[] rect_color;
private int rect_text_color;//矩形文字颜色
private int rect_big_text_color;//矩形最大文字颜色
private int rect_text_size;//矩形文字尺寸
private getNumberListener listener;
private int selectIndex = -1;
private int yHeightSelect=0;
private int leftSelector=0;
private boolean isScrollow;//true 滑动 false点击
private List<Integer> selectIndexRoles = new ArrayList<>();
private List<Object> objects=new ArrayList<>();
public HistogramRound(Context context) {
super(context);
}
public HistogramRound(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initStyle(context,attrs);
}
public HistogramRound(Context context, AttributeSet attrs) {
super(context, attrs);
initStyle(context,attrs);
}
/*
* 初始化样式属性
*/
private void initStyle(Context context,AttributeSet attrs) {
TypedArray types = context.obtainStyledAttributes(attrs, R.styleable.zqxchart_histogram);
coordinates_color = types.getColor(R.styleable.zqxchart_histogram_hCoordinatesColor, Color.RED);
rect_text_color = types.getColor(R.styleable.zqxchart_histogram_rectTextColor,Color.BLACK);
rect_big_text_color=getResources().getColor(R.color.text_yellow);
rect_text_size = types.getInteger(R.styleable.zqxchart_histogram_rectTextSize,28);
x_text_color = types.getColor(R.styleable.zqxchart_histogram_hxTextColor,Color.BLACK);
y_text_color = types.getColor(R.styleable.zqxchart_histogram_hyTextColor,Color.BLACK);
x_text_size = types.getInteger(R.styleable.zqxchart_histogram_hxTextSize,30);
y_text_size = types.getInteger(R.styleable.zqxchart_histogram_hyTextSize,28);
xpCount = types.getInteger(R.styleable.zqxchart_histogram_hxPointCount,12);
ypCount = types.getInteger(R.styleable.zqxchart_histogram_hyPointCount,12);
rect_color = getResources().getIntArray(R.array.histogram_color);
animType = types.getInteger(R.styleable.zqxchart_histogram_hanimType, Anim.ANIM_NONE);
types.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (xData!=null&&yData!=null){
drawHistogramRound(canvas);
}
}
/*
* 画柱状图
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void drawHistogramRound(Canvas canvas) {
//如果没有设置x轴数据
if (xData == null){
throw new NullPointerException("x轴数据源不能为空!");
}
//如果没有设置y轴数据
if (yData == null){
throw new NullPointerException("y轴数据源不能为空!");
}
Paint histogramPaint = new Paint();
// histogramPaint.setAntiAlias(true);
histogramPaint.setStyle(Paint.Style.FILL);
histogramPaint.setStrokeWidth((float) 4.0);
histogramPaint.setStrokeCap(Paint.Cap.ROUND);
//矩形上具体数据画笔
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// tv_mudi.setTextSize(TypedValue.COMPLEX_UNIT_PX,getResources().getDimension(R.dimen.font_13));
// textPaint.setTextSize(rect_text_size);
Paint mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
// mPaintCircle.setStyle(Paint.Style.ANTI_ALIAS_FLAG);
//
mPaintCircle.setStrokeWidth(2);
mPaintCircle.setColor(Color.parseColor("#ff5932"));
mPaintCircle.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0));
mPaintCircle.setAntiAlias(true);
textPaint.setTextSize(getResources().getDimension(R.dimen.font_9));
DecimalFormat formater = new DecimalFormat("0.000");
for (int i=0; i<xpCount; i++){
try {
histogramPaint.setColor(rect_color == null
? getResources().getColor(R.color.colorPrimary)
: rect_color[i]);
}catch (ArrayIndexOutOfBoundsException e){
histogramPaint.setColor(getResources().getColor(R.color.colorPrimary));
}
int alpha = anims[i].getAlpha();
textPaint.setAlpha(alpha);
histogramPaint.setAlpha(alpha);
//计算执行动画当前y坐标
float top = anims[i].getCurrentY();
float left = oX+xCoordinates[i]-xSpacing/5;
float right = oX+xCoordinates[i]+xSpacing/3;
String a = formater.format(yData[i]);
String ydata=a.substring(0,a.indexOf("."));
int[] textSize = getTextSize(xData[i],textPaint);
float textY = top - textSize[1]/2;
LogUtil2.log("yMax-------"+yMax+"--ydata--"+ydata);
if (Float.valueOf(ydata)>=yMax){
textPaint.setColor(rect_big_text_color);
}else {
textPaint.setColor(rect_text_color);
}
LogUtil2.log("yData--------------->ydataY轴上的数据"+ydata);
//画矩形上文字
// canvas.drawText(ydata,left+20,textY,textPaint);
//计算每条柱状图的宽度
// double tempBarWidth = (((int) mXinterval) >> 1) / mCategoryList.size();
// mBarPaint.setStrokeWidth((float) tempBarWidth);
if (selectIndex==i){
histogramPaint.setColor(ContextCompat.getColor(getContext(), R.color.name_ffa646));
//draw x 坐标
yHeightSelect= (int) top/*-getPaddingTop() */- getPaddingBottom()-xTextSurplus-x_text_size;
yHeightSelect= (int) (/*(oY+75)-(*/top/*+getPaddingTop()/)*/);
leftSelector= (int) (left+(right-left)/2);
// canvas.drawLine(oX,top, oX,top-yHeight,mPaintCircle);
Path path = new Path();
path.moveTo(oX, oX+xWidth+40);
path.lineTo(oX, oX+xWidth+40);
// canvas.drawPath(path, mPaintCircle);
// canvas.drawLine(oX,top,oX+xWidth+40,top,mPaintCircle);
if (!isScrollow){
listener.getNumber(i, (int) oY, leftSelector,yHeightSelect, (int) oX);
}
LogUtil2.log("setSelect--画:--getHeight"+getHeight()+"--left--"+left+"--height--"+yHeightSelect+"--top--"+top+"--oy--"+oY);
}else {
histogramPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_1FA6FB));
}
//画每一个矩形
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
//画圆角柱只在5.0以上版本适用,以下版本会闪退
canvas.drawRoundRect(left,top,right,oY,30,30,histogramPaint);
}else {
canvas.drawRect(left,top,right,oY,histogramPaint);
}
objects.add(histogramPaint);
}
}
public void setPublicRefresh(){
selectIndex=-1;
invalidate();
for (int i=0;i<objects.size();i++){
Paint paint= (Paint) objects.get(i);
paint.setColor(ContextCompat.getColor(getContext(), R.color.color_1FA6FB));
LogUtil2.log("柱子--"+paint);
}
}
// public void isScrollow(boolean isScrollowt){
// this.isScrollow=isScrollowt;
// };
/*
* 设置数据
*/
@Override
public void setChartYdateData(ChartData chartData) {
super.setChartYdateData(chartData);
HistogramData histogramData = (HistogramData) chartData;
this.rect_color = histogramData.getRectColor() != null ?
histogramData.getRectColor() : this.rect_color;
this.rect_text_size = getFinalValue(this.rect_text_size,histogramData.getRectTextSize());
this.rect_text_color = getFinalValue(this.rect_text_color,histogramData.getRectTextColor());
}
@Override
public void setOnLongClickListener(@Nullable OnLongClickListener l) {
super.setOnLongClickListener(l);
LogUtil2.log("onDraw--getX---弹框的长按事件:" + isScrollow);
}
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
LogUtil2.log("onDraw--getX---弹框的滑动事件:" + isScrollow);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
LogUtil2.log("onDraw--getX---弹框的滑动改变事件:" + isScrollow);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int x =0;
int y =0;
int left = getPaddingLeft()+yTextSurplus;
int top = 0;
int right = xWidth/ 12+getPaddingLeft()+yTextSurplus;
int bottom = yHeight;
// int right = getWidth()/ 12;
// int bottom = yHeight;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
x = (int) ev.getX();
y = (int) ev.getY();
LogUtil2.log("setSelect--666down--x" + x + "--left--" + y + "ev--x" + ev.getX() + "ev--y" + ev.getY());
// if (isScrollow) {
/* for (int i = 0; i < 12; i++) {
Rect rect = new Rect(left, top, right, bottom);
left += xWidth / 12;
right += xWidth / 12;
if (rect.contains(x, y)) {
if (listener != null) {
LogUtil2.log("setSelect--666down--x" + x + "--left--" + y + "ev--x" + ev.getX() + "ev--y" + ev.getY());
//抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
// if (Math.abs(ArithUtil.sub(ev.getX(), x)) <= 20 && Math.abs(ArithUtil.sub(ev.getY(), y)) <= 20) {
selectIndex = i;
selectIndexRoles.clear();
se