package cn.androidy.thinking.views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import cn.androidy.thinking.charting.ChartingUtils;
import cn.androidy.thinking.charting.data.Entry;
import cn.androidy.thinking.charting.data.EntryScreen;
public class TemperatureCurveView extends View {
List<Entry> entries = new ArrayList<>();
/**
* main paint object used for rendering
*/
protected Paint mRenderPaint;
protected Paint textPaint;
protected Path cubicPath = new Path();
protected Path cubicFillPath = new Path();
protected int xIndexWidth;
protected DisplayMetrics dm;
protected float mRange;
protected float maxVal;
protected float minVal;
float phaseX = 1;
float phaseY = 1;
float scale = 1;
public float getPhaseX() {
return phaseX;
}
public float getPhaseY() {
return phaseY;
}
public void setPhaseX(float phaseX) {
this.phaseX = phaseX;
invalidate();
}
public void setPhaseY(float phaseY) {
this.phaseY = phaseY;
invalidate();
}
public TemperatureCurveView(Context context) {
this(context, null);
}
public TemperatureCurveView(Context context, AttributeSet attrs) {
super(context, attrs);
dm = getResources().getDisplayMetrics();
mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRenderPaint.setStyle(Paint.Style.FILL);
mRenderPaint.setStrokeWidth(3);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(12 * dm.density);
Random random = new Random();
for (int i = 0; i < 15; i++) {
entries.add(new Entry(1 + random.nextInt(9) * 0.1f, i));
}
maxVal = ChartingUtils.getMaxVal(entries);
minVal = ChartingUtils.getMinVal(entries);
mRange = maxVal - minVal;
xIndexWidth = dm.widthPixels / (entries.size() - 1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
for (int i = 0; i < entries.size(); i++) {
entries.get(i).setEntryScreen(new EntryScreen(maxVal, minVal, getTop(), getBottom()));
}
scale = Math.abs(getHeight() / (maxVal - minVal)) * 0.1f;
}
@Override
protected void onDraw(Canvas canvas) {
int minx = 0;
int maxx = entries.size();
float intensity = 0.2f;
cubicPath.reset();
int size = (int) Math.ceil((maxx - minx) * phaseX + minx);
if (size - minx >= 2) {
float prevDx = 0f;
float prevDy = 0f;
float curDx = 0f;
float curDy = 0f;
Entry prevPrev = entries.get(minx);
Entry prev = entries.get(minx);
Entry cur = entries.get(minx);
Entry next = entries.get(minx + 1);
// let the spline start
cubicPath.moveTo(cur.getXIndex(), cur.findYCoordinate(phaseY, scale));
prevDx = (cur.getXIndex() - prev.getXIndex()) * intensity;
prevDy = (cur.findYCoordinate(phaseY, scale) - prev.findYCoordinate(phaseY, scale)) * intensity;
curDx = (next.getXIndex() - cur.getXIndex()) * intensity;
curDy = (next.findYCoordinate(phaseY, scale) - cur.findYCoordinate(phaseY, scale)) * intensity;
// the first cubic
cubicPath.cubicTo(xIndexWidth * (prev.getXIndex() + prevDx), (prev.findYCoordinate(phaseY, scale) + prevDy),
xIndexWidth * (cur.getXIndex() - curDx),
(-curDy), cur.getXIndex() * xIndexWidth, cur.findYCoordinate(phaseY, scale));
canvas.drawText(String.valueOf(cur.getVal()), cur.getXIndex() * xIndexWidth, cur.findYCoordinate(phaseY, scale), textPaint);
for (int j = minx + 1, count = Math.min(size, entries.size() - 1); j < count; j++) {
prevPrev = entries.get(j == 1 ? 0 : j - 2);
prev = entries.get(j - 1);
cur = entries.get(j);
next = entries.get(j + 1);
prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity;
prevDy = (cur.findYCoordinate(phaseY, scale) - prevPrev.findYCoordinate(phaseY, scale)) * intensity;
curDx = (next.getXIndex() - prev.getXIndex()) * intensity;
curDy = (next.findYCoordinate(phaseY, scale) - prev.findYCoordinate(phaseY, scale)) * intensity;
cubicPath.cubicTo(xIndexWidth * (prev.getXIndex() + prevDx), (prev.findYCoordinate(phaseY, scale) + prevDy),
xIndexWidth * (cur.getXIndex() - curDx),
(cur.findYCoordinate(phaseY, scale) - curDy), cur.getXIndex() * xIndexWidth, cur.findYCoordinate(phaseY, scale));
canvas.drawText(String.valueOf(cur.getVal()), cur.getXIndex() * xIndexWidth, cur.findYCoordinate(phaseY, scale), textPaint);
}
if (size > entries.size() - 1) {
prevPrev = entries.get((entries.size() >= 3) ? entries.size() - 3
: entries.size() - 2);
prev = entries.get(entries.size() - 2);
cur = entries.get(entries.size() - 1);
next = cur;
prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity;
prevDy = (cur.findYCoordinate(phaseY, scale) - prevPrev.findYCoordinate(phaseY, scale)) * intensity;
curDx = (next.getXIndex() - prev.getXIndex()) * intensity;
curDy = (next.findYCoordinate(phaseY, scale) - prev.findYCoordinate(phaseY, scale)) * intensity;
// the last cubic
cubicPath.cubicTo(xIndexWidth * (prev.getXIndex() + prevDx), (prev.findYCoordinate(phaseY, scale) + prevDy),
xIndexWidth * (cur.getXIndex() - curDx),
(cur.findYCoordinate(phaseY, scale) - curDy), cur.getXIndex() * xIndexWidth, cur.findYCoordinate(phaseY, scale));
canvas.drawText(String.valueOf(cur.getVal()), cur.getXIndex() * xIndexWidth, cur.findYCoordinate(phaseY, scale), textPaint);
}
}
cubicFillPath.reset();
cubicFillPath.addPath(cubicPath);
// create a new path, this is bad for performance
drawCubicFill(canvas, cubicFillPath, 0, size);
mRenderPaint.setColor(0xffed145b);
mRenderPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(cubicPath, mRenderPaint);
mRenderPaint.setPathEffect(null);
}
protected void drawCubicFill(Canvas canvas, Path spline,
int from, int to) {
spline.lineTo((to - 1) * xIndexWidth, getHeight());
spline.lineTo(from * xIndexWidth, getHeight());
spline.close();
mRenderPaint.setStyle(Paint.Style.FILL);
mRenderPaint.setColor(Color.BLUE);
// filled is drawn with less alpha
mRenderPaint.setAlpha(80);
canvas.drawPath(spline, mRenderPaint);
mRenderPaint.setAlpha(255);
}
}