Skip to content

Instantly share code, notes, and snippets.

@crearo
Last active July 13, 2017 05:54
Show Gist options
  • Save crearo/9e3d75de2734834009663ba539adaf20 to your computer and use it in GitHub Desktop.
Save crearo/9e3d75de2734834009663ba539adaf20 to your computer and use it in GitHub Desktop.
A simple line graph view that renders at 60fps. Fast, elegant.
package rish.crearo.imagestabv2;
/**
* Original author unknown.
*
* Modified by rish on 10/7/17.
* [email protected]
*/
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class LineGraphView extends View {
private static final String TAG = LineGraphView.class.getSimpleName();
private static final int UPDATE_DELAY = 16; // 60 FPS
private static final int TEXT_SIZE = 10;
private final Handler mHandler = new Handler();
private final Paint mPaint = new Paint();
private float[] mData;
private int mFramePos = 0;
private int mWidth = 0;
private float mMaxAbsValue = 0;
private float mCurrValue = 0;
private int mBackgroundColor = 0xFF202020;
private int mAxisColor = 0xFF708090;
private int mDataColor = 0xFFFF8090;
private boolean mIsAttached = false;
private int mStringHeight;
private int mStringWidth;
private final Runnable mUpdateRunnable = new Runnable() {
@Override
public void run() {
// shift mData
mFramePos++;
if (mFramePos == mWidth - 1) {
mFramePos = 0;
// shift mData
System.arraycopy(mData, (mWidth - 1) * 4, mData, 0, mData.length / 2);
// fill X
fillX();
} else {
mData[(mFramePos + mWidth - 1) * 4 + 1] = mData[(mFramePos - 1 + mWidth - 1) * 4 + 3];
mData[(mFramePos + mWidth - 1) * 4 + 3] = mCurrValue;
}
invalidate();
if (mIsAttached) mHandler.postDelayed(mUpdateRunnable, UPDATE_DELAY);
}
};
public LineGraphView(Context context) {
super(context);
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE,
getResources().getDisplayMetrics()));
}
public LineGraphView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint.setTextSize(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE, getResources().getDisplayMetrics()));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mFramePos = 0;
mData = new float[(mWidth * 2 - 1) * 4];
clearData();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mIsAttached = true;
mHandler.postDelayed(mUpdateRunnable, UPDATE_DELAY);
}
@Override
protected void onDetachedFromWindow() {
mIsAttached = false;
mHandler.removeCallbacks(mUpdateRunnable);
super.onDetachedFromWindow();
}
private void clearData() {
for (int x = 0; x < mData.length / 4; ++x) {
mData[x * 4] = x;
mData[x * 4 + 1] = 0;
mData[x * 4 + 2] = x + 1;
mData[x * 4 + 3] = 0;
}
}
public void setValue(float value) {
mCurrValue = value;
setAbsValue(value);
}
private void setAbsValue(float value) {
if (Math.abs(value) > Math.abs(mMaxAbsValue)) mMaxAbsValue = value;
}
public void clear() {
if (mData == null) return;
clearData();
mMaxAbsValue = mCurrValue = 0;
}
@Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
if (width != this.mWidth) return;
canvas.drawColor(mBackgroundColor);
canvas.save();
canvas.translate(0, height / 2 - 1);
canvas.scale(1, 10);
{
// axis
mPaint.setColor(mAxisColor);
canvas.drawLine(0, 0, width - 1, 0, mPaint);
// mData
if (mData != null) {
mPaint.setColor(mDataColor);
canvas.translate(-mFramePos, 0);
canvas.drawLines(mData, mFramePos * 4, (width - 1) * 4, mPaint);
}
}
canvas.restore();
// text
mPaint.setColor(mAxisColor);
if (mStringHeight == 0)
mStringHeight = Math.round(Math.abs(mPaint.ascent()) + mPaint.descent() + 0.5f);
if (mStringWidth == 0) mStringWidth = Math.round(mPaint.measureText("00.00") + 0.5f);
String str = String.format("%.1f", mMaxAbsValue);
canvas.drawText(str, width - 2 - mStringWidth, 1 + mStringHeight, mPaint);
str = String.format("%.1f", mCurrValue);
canvas.drawText(str, width - 2 - mStringWidth, height - mPaint.descent(), mPaint);
}
private void fillX() {
for (int x = 0; x < mData.length / 4; ++x) {
mData[x * 4] = x;
mData[x * 4 + 2] = x + 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment