自己的项目碰到需要自定义圆头柱状图,记录下来
public abstract class BaseCoordinateView extends View {
public static final String TAG = "MChartView";
private RectF mRealRect0;
private RectF mRealRect1;
private RectF mRealRect2;
private Paint mXAxisPaint;
private Paint mYAxisPaint;
private PointF mOriginPoint;
private boolean mNeedXAxis = true, mNeedYAxis = true;
public BaseCoordinateView(Context context, AttributeSet attrs) {
super(context, attrs);
init0(attrs);
}
public BaseCoordinateView(Context context) {
super(context);
init0(null);
}
private void init0(AttributeSet attrs) {
float _1dp = ViewUtils.dp2px(getContext(), 1);
float xStroke = _1dp * 1.0f;
mXAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mXAxisPaint.setStrokeWidth(xStroke);
mXAxisPaint.setColor(Color.parseColor("#9b9b9b"));
mXAxisPaint.setStyle(Paint.Style.FILL);
float yStroke = _1dp * 1.0f;
mYAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mYAxisPaint.setStrokeWidth(yStroke);
mYAxisPaint.setColor(Color.LTGRAY);
mYAxisPaint.setStyle(Paint.Style.FILL);
mOriginPoint = new PointF();
}
public void reDraw() {
mRealRect0 = null;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (getWidth() + getHeight() <= 0) return;
if (mRealRect0 == null) {
initRealRect();
}
if (mNeedXAxis) {
drawXAxis(canvas);
}
if (mNeedYAxis) {
drawYAxis(canvas);
}
mRealRect1.set(mRealRect0); // avoid alloc, different rectangle
mRealRect2.set(mRealRect0);
beforeDraw(canvas, mRealRect1);
drawChart(canvas, mRealRect2);
}
private void initRealRect() {
mRealRect0 = new RectF();
mRealRect0.left = getPaddingLeft();
mRealRect0.right = getWidth() - getPaddingRight();
mRealRect0.top = getPaddingTop();
mRealRect0.bottom = getHeight() - getPaddingBottom();
narrowMainRect(mRealRect0);
mOriginPoint.set(mRealRect0.left, mRealRect0.bottom);
mRealRect1 = new RectF();
mRealRect2 = new RectF();
}
protected void needXAxis(boolean isNeed) {
mNeedXAxis = isNeed;
}
protected void needYAxis(boolean isNeed) {
mNeedYAxis = isNeed;
}
/**
* Before the content draws, after draw axis.
*
* @param c
* @param realRect
*/
protected void beforeDraw(Canvas c, RectF realRect) {
}
protected abstract void drawChart(Canvas c, RectF realRect);
protected void narrowMainRect(RectF rectF) {
int padding = ViewUtils.dp2px(getContext(), 5);
ViewUtils.narrowRectF(rectF, padding);
}
public Paint getXAxisPaint() {
return mXAxisPaint;
}
public Paint getYAxisPaint() {
return mYAxisPaint;
}
private void drawXAxis(Canvas c) {
// move down to draw x axis
float offset = getXAxisOffset();
c.drawLine(mOriginPoint.x, mOriginPoint.y + offset, mRealRect0.right, mOriginPoint.y + offset, mXAxisPaint);
}
protected float getXAxisOffset() {
return mXAxisPaint.getStrokeWidth() / 2;
}
private void drawYAxis(Canvas c) {
// move left to draw y axis
float offset = getYAxisOffset();
c.drawLine(mOriginPoint.x - offset, mOriginPoint.y, mOriginPoint.x - offset, mRealRect0.top, mYAxisPaint);
}
protected float getYAxisOffset() {
return mYAxisPaint.getStrokeWidth() / 2;
}
}
public abstract class AbsPartsChartView extends BaseCoordinateView {
/**
* exactly same as list.size
* initialized in #setDatas()
*/
protected int COUNT = -1;
protected float MAX = 100;
private float mPaddingLeft = 0.0f, mPaddingRight = 0.0f;
private List<Item> mItemList;
private List<PointF> mPointList;
private boolean mPointInited = false; //
protected int mNormalColor = 0xFFf1e9e9, mHighLightColor = 0xFFffc107;
public AbsPartsChartView(Context context) {
super(context);
}
public AbsPartsChartView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* draw the paddings of item INSIDE the coordinate
*
* @param l left
* @param t top
* @param r right
* @param b bottom
*/
public void setInnerPadding(float l, float t, float r, float b) {
mPaddingLeft = l;
mPaddingRight = r;
}
public void setColors(int normal, int highLight) {
mNormalColor = normal;
mHighLightColor = highLight;
}
@Override
protected void drawChart(Canvas c, RectF realRect) {
if (!mPointInited) {
makePoints(realRect);
}
for (int i = 0; i < COUNT; i++) {
PointF p = mPointList.get(i);
Item item = mItemList.get(i);
drawItem(c, item, p, realRect);
}
}
private void makePoints(RectF rect) {
float width = rect.right - rect.left - mPaddingLeft - mPaddingRight;
float height = rect.bottom - rect.top;
float partWidth = width / (COUNT - 1);
float startX = rect.left + mPaddingLeft;
float startY = rect.bottom;// should bottom rect.top -> rect.bottom
for (int i = 0; i < COUNT; i++) {
Item item = mItemList.get(i);
float progress = item.progress;
float x = startX + i * partWidth;
float y;
if(progress > 0){
y = startY - progress / MAX * height;
if(y < 0){
y = rect.top;
}
}else {
y = -1;
}
PointF p = mPointList.get(i);
p.set(x, y);
}
mPointInited = true;
}
protected abstract int drawItem(Canvas c, Item item, PointF itemPoint, RectF realRect);
public void setDatas(List<Item> list) {
setDatas(list, true);
}
public void setDatas(List<Item> list, boolean needInvalidate) {
mItemList = list;
COUNT = mItemList.size();
mPointList = new ArrayList<PointF>(COUNT);
for (int i = 0; i < COUNT; i++) {
PointF p = new PointF();
mPointList.add(p);
}
mPointInited = false;
if (needInvalidate) {
invalidate();
}
}
public void setMax(float max) {
MAX = max;
}
public class Item {
public float progress;
public boolean highLight = false;
}
}
public class HistogramChartView extends AbsPartsChartView {
private float mRectWidth;
private Paint mRectPaint;
private Paint mPointPaint;
public HistogramChartView(Context context) {
super(context);
init();
}
public HistogramChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
protected void init() {
mPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPointPaint.setStyle(Paint.Style.FILL);
mPointPaint.setStrokeWidth(5);
mPointPaint.setColor(Color.RED);
mRectWidth = ViewUtils.dp2px(getContext(), 10);
mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRectPaint.setStyle(Paint.Style.FILL);
mRectPaint.setColor(mNormalColor);
}
@Override
protected int drawItem(Canvas c, Item item, PointF itemPoint, RectF realRect) {
if (itemPoint.y > 0) {
mRectPaint.setColor(item.highLight ? mHighLightColor : mNormalColor);
RectF rect = makeHistogramRect(itemPoint, realRect.bottom, mRectWidth);
// c.drawRect(rect, mRectPaint);
// TODO: 2016/7/1 17:04modify ---
RoundRectShape rr = new RoundRectShape(new float[]{8, 8, 8, 8, 0, 0, 0, 0}, null, null);
ShapeDrawable shapeDrawable = new ShapeDrawable(rr);
shapeDrawable.getPaint().setColor(mRectPaint.getColor());
Rect r = new Rect();
rect.round(r);
shapeDrawable.setBounds(r);
shapeDrawable.draw(c);
//---
}
return 0;
}
private RectF makeHistogramRect(PointF p, float bottom, float width) {
RectF rect = new RectF();
rect.left = p.x - width / 2;
rect.right = p.x + width / 2;
rect.top = p.y;
rect.bottom = bottom;
return rect;
}