123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795 |
- // Copyright (c) 2010, Freddy Martens (http://atstechlab.wordpress.com),
- // MindTheRobot (http://mindtherobot.com/blog/) and contributors
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without modification,
- // are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- // * Neither the name of Ondrej Zara nor the names of its contributors may be used
- // to endorse or promote products derived from this software without specific
- // prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- package nl.digitalthings.mebarista;
- import nl.digitalthings.mebarista.R;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.BitmapShader;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.LinearGradient;
- import android.graphics.Matrix;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.graphics.RadialGradient;
- import android.graphics.RectF;
- import android.graphics.Shader;
- import android.graphics.Typeface;
- import android.os.Bundle;
- import android.os.Parcelable;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.View;
- import android.content.res.TypedArray;
- public final class Gauge extends View {
- private static final String TAG = Gauge.class.getSimpleName();
-
- // drawing tools
- private RectF rimRect;
- private Paint rimPaint;
- private Paint rimCirclePaint;
-
- private RectF faceRect;
- private Bitmap faceTexture;
- private Paint facePaint;
- private Paint rimShadowPaint;
-
- private Paint scalePaint;
- private RectF scaleRect;
- private RectF valueRect;
- private RectF rangeRect;
- private Paint rangeOkPaint;
- private Paint rangeWarningPaint;
- private Paint rangeErrorPaint;
- private Paint rangeAllPaint;
-
- private Paint valueOkPaint;
- private Paint valueWarningPaint;
- private Paint valueErrorPaint;
- private Paint valueAllPaint;
-
- private Paint unitPaint;
- private Path unitPath;
- private RectF unitRect;
- private Paint lowerTitlePaint;
- private Paint upperTitlePaint;
- private Path lowerTitlePath;
- private Path upperTitlePath;
- private RectF titleRect;
- private Paint handPaint;
- private Path handPath;
- private Paint handScrewPaint;
-
- private Paint backgroundPaint;
- // end drawing tools
-
- private Bitmap background; // holds the cached static part
-
- // scale configuration
- // Values passed as property. Defaults are set here.
- private boolean showHand = true;
- private boolean showGauge = false;
- private boolean showRange = false;
-
- private int totalNotches = 120; // Total number of notches on the scale.
- private int incrementPerLargeNotch = 10;
- private int incrementPerSmallNotch = 2;
- private int scaleColor = 0x9f004d0f;
- private int scaleCenterValue = 0; // the one in the top center (12 o'clock), this corresponds with -90 degrees
- private int scaleMinValue = -90;
- private int scaleMaxValue = 120;
- private int angleMinValue = -120;
- private int angleMaxValue = 120;
- private float degreeMinValue = 0;
- private float degreeMaxValue = 0;
- private int rangeOkColor = 0x9f00ff00;
- private int rangeOkMinValue = scaleMinValue;
- private int rangeOkMaxValue = 45;
- private float degreeOkMinValue = 0;
- private float degreeOkMaxValue = 0;
- private int rangeWarningColor = 0x9fff8800;
- private int rangeWarningMinValue = rangeOkMaxValue;
- private int rangeWarningMaxValue = 80;
- private float degreeWarningMinValue = 0;
- private float degreeWarningMaxValue = 0;
- private int rangeErrorColor = 0x9fff0000;
- private int rangeErrorMinValue = rangeWarningMaxValue;
- private int rangeErrorMaxValue = 120;
- private float degreeErrorMinValue = 0;
- private float degreeErrorMaxValue = 0;
-
- private String lowerTitle = "www.ats-global.com";
- private String upperTitle = "Visit http://atstechlab.wordpress.com";
- private String unitTitle = "\u2103";
- // Fixed values.
- private static float scalePosition = 0.10f; // The distance from the rim to the scale
- private static float valuePosition = 0.285f; // The distance from the rim to the ranges
- private static float rangePosition = 0.122f; // The distance from the rim to the ranges
- private static float titlePosition = 0.145f; // The Distance from the rim to the titles
- private static float unitPosition = 0.300f; // The distance from the rim to the unit
- private static float rimSize = 0.02f;
- private float degreesPerNotch = 360.0f/totalNotches;
- private static final int centerDegrees = -90; // the one in the top center (12 o'clock), this corresponds with -90 degrees
- // hand dynamics
- private boolean dialInitialized = false;
- private float currentValue = scaleCenterValue;
- private float targetValue = scaleCenterValue;
- private float dialVelocity = 0.0f;
- private float dialAcceleration = 0.0f;
- private long lastDialMoveTime = -1L;
-
-
- public Gauge(Context context) {
- super(context);
- init(context, null);
- }
- public Gauge(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context, attrs);
- }
- public Gauge(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(context, attrs);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- }
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- Bundle bundle = (Bundle) state;
- Parcelable superState = bundle.getParcelable("superState");
- super.onRestoreInstanceState(superState);
-
- dialInitialized = bundle.getBoolean("dialInitialized");
- currentValue = bundle.getFloat("currentValue");
- targetValue = bundle.getFloat("targetValue");
- dialVelocity = bundle.getFloat("dialVelocity");
- dialAcceleration = bundle.getFloat("dialAcceleration");
- lastDialMoveTime = bundle.getLong("lastDialMoveTime");
- }
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
-
- Bundle state = new Bundle();
- state.putParcelable("superState", superState);
- state.putBoolean("dialInitialized", dialInitialized);
- state.putFloat("currentValue", currentValue);
- state.putFloat("targetValue", targetValue);
- state.putFloat("dialVelocity", dialVelocity);
- state.putFloat("dialAcceleration", dialAcceleration);
- state.putLong("lastDialMoveTime", lastDialMoveTime);
- return state;
- }
- private void init(Context context, AttributeSet attrs) {
- // Get the properties from the resource file.
- // setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- if (context != null && attrs != null){
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Dial);
- showRange = a.getBoolean(R.styleable.Dial_showRange, showRange);
- showGauge = a.getBoolean(R.styleable.Dial_showGauge, showGauge);
- //showHand = a.getBoolean(R.styleable.Dial_showHand, showHand);
- totalNotches = a.getInt(R.styleable.Dial_totalNotches, totalNotches);
- incrementPerLargeNotch = a.getInt(R.styleable.Dial_incrementPerLargeNotch, incrementPerLargeNotch);
- incrementPerSmallNotch = a.getInt(R.styleable.Dial_incrementPerSmallNotch, incrementPerSmallNotch);
- scaleCenterValue = a.getInt(R.styleable.Dial_scaleCenterValue, scaleCenterValue);
- scaleColor = a.getInt(R.styleable.Dial_scaleColor, scaleColor);
- scaleMinValue = a.getInt(R.styleable.Dial_scaleMinValue, scaleMinValue);
- scaleMaxValue = a.getInt(R.styleable.Dial_scaleMaxValue, scaleMaxValue);
- angleMinValue = a.getInt(R.styleable.Dial_angleMinValue, angleMinValue);
- angleMaxValue = a.getInt(R.styleable.Dial_angleMaxValue, angleMaxValue);
- rangeOkColor = a.getInt(R.styleable.Dial_rangeOkColor, rangeOkColor);
- rangeOkMinValue = a.getInt(R.styleable.Dial_rangeOkMinValue, rangeOkMinValue);
- rangeOkMaxValue = a.getInt(R.styleable.Dial_rangeOkMaxValue, rangeOkMaxValue);
- rangeWarningColor = a.getInt(R.styleable.Dial_rangeWarningColor, rangeWarningColor);
- rangeWarningMinValue = a.getInt(R.styleable.Dial_rangeWarningMinValue, rangeWarningMinValue);
- rangeWarningMaxValue = a.getInt(R.styleable.Dial_rangeWarningMaxValue, rangeWarningMaxValue);
- rangeErrorColor = a.getInt(R.styleable.Dial_rangeErrorColor, rangeErrorColor);
- rangeErrorMinValue = a.getInt(R.styleable.Dial_rangeErrorMinValue, rangeErrorMinValue);
- rangeErrorMaxValue = a.getInt(R.styleable.Dial_rangeErrorMaxValue, rangeErrorMaxValue);
- String unitTitle = a.getString(R.styleable.Dial_unitTitle);
- String lowerTitle = a.getString(R.styleable.Dial_lowerTitle);
- String upperTitle = a.getString(R.styleable.Dial_upperTitle);
- if (unitTitle != null) this.unitTitle = unitTitle;
- if (lowerTitle != null) this.lowerTitle = lowerTitle;
- if (upperTitle != null) this.upperTitle = upperTitle;
- }
- degreeMinValue = valueToAngle(scaleMinValue) + centerDegrees;
- degreeMaxValue = valueToAngle(scaleMaxValue) + centerDegrees;
- degreeOkMinValue = valueToAngle(rangeOkMinValue) + centerDegrees;
- degreeOkMaxValue = valueToAngle(rangeOkMaxValue) + centerDegrees;
- degreeWarningMinValue = valueToAngle(rangeWarningMinValue) + centerDegrees;
- degreeWarningMaxValue = valueToAngle(rangeWarningMaxValue) + centerDegrees;
- degreeErrorMinValue = valueToAngle(rangeErrorMinValue) + centerDegrees;
- degreeErrorMaxValue = valueToAngle(rangeErrorMaxValue) + centerDegrees;
- degreesPerNotch = ( angleMaxValue - angleMinValue )*1.0f / totalNotches;
- // initDrawingTools();
- }
- private void initDrawingTools() {
- // All drawing has been scaled to actual pixels because of :
- // https://groups.google.com/forum/#!msg/android-developers/eTxV4KPy1G4/tAe2zUPCjMcJ
- int w = getWidth(), h = getHeight();
- rimRect = new RectF(0.0f, 0.0f, getWidth() /* 1.0f */, getHeight() /* 1.0f */);
- scalePosition = 0.10f * getWidth(); // The distance from the rim to the scale
- valuePosition = 0.285f * getWidth(); // The distance from the rim to the ranges
- rangePosition = 0.122f * getWidth(); // The distance from the rim to the ranges
- titlePosition = 0.145f * getWidth(); // The Distance from the rim to the titles
- unitPosition = 0.300f * getWidth(); // The distance from the rim to the unit
- rimSize = 0.02f * getWidth();
- faceRect = new RectF();
- faceRect.set(rimRect.left + rimSize, rimRect.top + rimSize,
- rimRect.right - rimSize, rimRect.bottom - rimSize);
- scaleRect = new RectF();
- scaleRect.set(faceRect.left + scalePosition, faceRect.top + scalePosition,
- faceRect.right - scalePosition, faceRect.bottom - scalePosition);
- rangeRect = new RectF();
- rangeRect.set(faceRect.left + rangePosition, faceRect.top + rangePosition,
- faceRect.right - rangePosition, faceRect.bottom - rangePosition);
-
- valueRect = new RectF();
- valueRect.set(faceRect.left + valuePosition, faceRect.top + valuePosition,
- faceRect.right - valuePosition, faceRect.bottom - valuePosition);
- titleRect = new RectF();
- titleRect.set(faceRect.left + titlePosition, faceRect.top + titlePosition,
- faceRect.right - titlePosition, faceRect.bottom - titlePosition);
- unitRect = new RectF();
- unitRect.set(faceRect.left + unitPosition, faceRect.top + unitPosition,
- faceRect.right - unitPosition, faceRect.bottom - unitPosition);
-
- faceTexture = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.plastic);
- BitmapShader paperShader = new BitmapShader(faceTexture,
- Shader.TileMode.MIRROR,
- Shader.TileMode.MIRROR);
- Matrix paperMatrix = new Matrix();
- paperMatrix.setScale(1.0f / faceTexture.getWidth(),
- 1.0f / faceTexture.getHeight());
- paperShader.setLocalMatrix(paperMatrix);
- rimShadowPaint = new Paint();
- rimShadowPaint.setShader(new RadialGradient(0.5f * getWidth(), 0.5f * getHeight(), faceRect.width() / 2.0f,
- new int[]{0x00000000, 0x00000500, 0x50000500},
- new float[]{0.96f, 0.96f, 0.99f},
- Shader.TileMode.MIRROR));
- rimShadowPaint.setStyle(Paint.Style.FILL);
- // the linear gradient is a bit skewed for realism
- rimPaint = new Paint();
- rimPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- rimPaint.setShader(new LinearGradient(0.40f * getWidth(), 0.0f, 0.60f * getWidth(), 1.0f * getHeight(),
- Color.rgb(0xf0, 0xf5, 0xf0),
- Color.rgb(0x30, 0x31, 0x30),
- Shader.TileMode.CLAMP));
- rimCirclePaint = new Paint();
- //rimCirclePaint.setAntiAlias(true);
- rimCirclePaint.setStyle(Paint.Style.STROKE);
- rimCirclePaint.setColor(Color.argb(0x4f, 0x33, 0x36, 0x33));
- rimCirclePaint.setStrokeWidth(0.005f * getWidth() );
-
- facePaint = new Paint();
- facePaint.setFilterBitmap(true);
- facePaint.setStyle(Paint.Style.FILL);
- facePaint.setShader(paperShader);
- scalePaint = new Paint();
- scalePaint.setStyle(Paint.Style.STROKE);
- scalePaint.setColor(scaleColor);
- scalePaint.setStrokeWidth(0.005f * getWidth() );
- scalePaint.setAntiAlias(true);
- //
- // scalePaint.setTextSize(0.045f);
- // http://stackoverflow.com/questions/13974129/android-4-2-1-wrong-character-kerning-spacing
- scalePaint.setTextSize( 0.045f * getWidth() );
- scalePaint.setLinearText(true);
- scalePaint.setTypeface(Typeface.SANS_SERIF);
- scalePaint.setTextScaleX(0.8f);
- scalePaint.setTextAlign(Paint.Align.CENTER);
-
- rangeOkPaint = new Paint();
- rangeOkPaint.setStyle(Paint.Style.STROKE);
- rangeOkPaint.setColor(rangeOkColor);
- rangeOkPaint.setStrokeWidth(0.012f * getWidth() );
- rangeOkPaint.setAntiAlias(true);
- rangeWarningPaint = new Paint();
- rangeWarningPaint.setStyle(Paint.Style.STROKE);
- rangeWarningPaint.setColor(rangeWarningColor);
- rangeWarningPaint.setStrokeWidth(0.012f * getWidth() );
- rangeWarningPaint.setAntiAlias(true);
- rangeErrorPaint = new Paint();
- rangeErrorPaint.setStyle(Paint.Style.STROKE);
- rangeErrorPaint.setColor(rangeErrorColor);
- rangeErrorPaint.setStrokeWidth(0.012f * getWidth() );
- rangeErrorPaint.setAntiAlias(true);
- rangeAllPaint = new Paint();
- rangeAllPaint.setStyle(Paint.Style.STROKE);
- rangeAllPaint.setColor(0xcff8f8f8);
- rangeAllPaint.setStrokeWidth(0.012f * getWidth() );
- rangeAllPaint.setAntiAlias(true);
- rangeAllPaint.setShadowLayer(0.005f, -0.002f, -0.002f, 0x7f000000);
- valueOkPaint = new Paint();
- valueOkPaint.setStyle(Paint.Style.STROKE);
- valueOkPaint.setColor(rangeOkColor);
- valueOkPaint.setStrokeWidth(0.20f * getWidth() );
- valueOkPaint.setAntiAlias(true);
- valueWarningPaint = new Paint();
- valueWarningPaint.setStyle(Paint.Style.STROKE);
- valueWarningPaint.setColor(rangeWarningColor);
- valueWarningPaint.setStrokeWidth(0.20f * getWidth() );
- valueWarningPaint.setAntiAlias(true);
- valueErrorPaint = new Paint();
- valueErrorPaint.setStyle(Paint.Style.STROKE);
- valueErrorPaint.setColor(rangeErrorColor);
- valueErrorPaint.setStrokeWidth(0.20f * getWidth() );
- valueErrorPaint.setAntiAlias(true);
- valueAllPaint = new Paint();
- valueAllPaint.setStyle(Paint.Style.STROKE);
- valueAllPaint.setColor(0xcff8f8f8);
- valueAllPaint.setStrokeWidth(0.20f * getWidth() );
- valueAllPaint.setAntiAlias(true);
- valueAllPaint.setShadowLayer(0.005f, -0.002f, -0.002f, 0x7f000000);
- unitPaint = new Paint();
- unitPaint.setColor(0xaf0c0c0c);
- unitPaint.setAntiAlias(true);
- unitPaint.setTypeface(Typeface.DEFAULT_BOLD);
- unitPaint.setTextAlign(Paint.Align.CENTER);
- unitPaint.setTextSize(0.05f * getWidth() );
- unitPaint.setTextScaleX(0.8f);
- upperTitlePaint = new Paint();
- upperTitlePaint.setColor(0xaf0c0c0c);
- upperTitlePaint.setAntiAlias(true);
- upperTitlePaint.setTypeface(Typeface.DEFAULT_BOLD);
- upperTitlePaint.setTextAlign(Paint.Align.CENTER);
- upperTitlePaint.setTextSize(0.09f * getWidth() );
- upperTitlePaint.setTextScaleX(0.8f);
- lowerTitlePaint = new Paint();
- lowerTitlePaint.setColor(0xaf0c0c0c);
- lowerTitlePaint.setAntiAlias(true);
- lowerTitlePaint.setTypeface(Typeface.DEFAULT_BOLD);
- lowerTitlePaint.setTextAlign(Paint.Align.CENTER);
- lowerTitlePaint.setTextSize(0.04f * getWidth() );
- lowerTitlePaint.setTextScaleX(0.8f);
- handPaint = new Paint();
- handPaint.setAntiAlias(true);
- handPaint.setColor(0xff392f2c);
- //handPaint.setShadowLayer(0.01f, -0.005f, -0.005f, 0x7f000000);
- handPaint.setStyle(Paint.Style.FILL);
- handPaint.setStrokeWidth(0.1f);
- //handPaint.setColor(android.graphics.Color.RED);
- //handPaint.setStyle(Paint.Style.STROKE);
- handScrewPaint = new Paint();
- handScrewPaint.setAntiAlias(true);
- //handScrewPaint.setColor(0xff493f3c);
- handScrewPaint.setColor(0xffff3f3c);
- handScrewPaint.setStyle(Paint.Style.FILL);
-
- backgroundPaint = new Paint();
- backgroundPaint.setFilterBitmap(true);
- unitPath = new Path();
- unitPath.addArc(unitRect, 180.0f, 180.0f);
- upperTitlePath = new Path();
- upperTitlePath.addArc(titleRect, 180.0f, 180.0f);
- lowerTitlePath = new Path();
- lowerTitlePath.addArc(titleRect, -180.0f, -180.0f);
- // The hand is drawn with the tip facing up. That means when the image is not rotated, the tip
- // faces north. When the the image is rotated -90 degrees, the tip is facing west and so on.
- handPath = new Path();
- // handPath.setFillType(Path.FillType.EVEN_ODD);// X Y
- handPath.moveTo(0.5f * w, (0.5f + 0.2f) * h); // 0.500, 0.700
- handPath.lineTo( ( 0.5f - 0.010f ) * w, ( 0.5f + 0.2f - 0.007f ) * h); // 0.490, 0.630
- handPath.lineTo( ( 0.5f - 0.002f ) * w, ( 0.5f - 0.40f ) * h); // 0.498, 0.100
- handPath.lineTo( ( 0.5f + 0.002f ) * w, ( 0.5f - 0.40f ) * h); // 0.502, 0.100
- handPath.lineTo((0.5f + 0.010f) * w, (0.5f + 0.2f - 0.007f) * h); // 0.510, 0.630
- //handPath.lineTo(0.5f * w, 0.5f + 0.2f * h); // 0.500, 0.700
- handPath.addCircle(0.5f * w, 0.5f * h, 0.025f * w, Path.Direction.CW);
- handPath.close();
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- //Log.d(TAG, "Width spec: " + MeasureSpec.toString(widthMeasureSpec));
- //Log.d(TAG, "Height spec: " + MeasureSpec.toString(heightMeasureSpec));
-
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int chosenWidth = chooseDimension(widthMode, widthSize);
- int chosenHeight = chooseDimension(heightMode, heightSize);
-
- int chosenDimension = Math.min(chosenWidth, chosenHeight);
-
- setMeasuredDimension(chosenDimension, chosenDimension);
- }
-
- private int chooseDimension(int mode, int size) {
- if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
- return size;
- } else { // (mode == MeasureSpec.UNSPECIFIED)
- return getPreferredSize();
- }
- }
-
- // in case there is no size specified
- private int getPreferredSize() {
- return 250;
- }
- private void drawRim(Canvas canvas) {
- // first, draw the metallic body
- canvas.drawOval(rimRect, rimPaint);
- // now the outer rim circle
- canvas.drawOval(rimRect, rimCirclePaint);
- }
-
- private void drawFace(Canvas canvas) {
- canvas.drawOval(faceRect, facePaint);
- // draw the inner rim circle
- // was: canvas.drawOval(faceRect, rimCirclePaint);
- canvas.drawOval(faceRect, rimCirclePaint);
- // draw the rim shadow inside the face
- canvas.drawOval(faceRect, rimShadowPaint); // boosdoener
- }
- private void drawBackground(Canvas canvas) {
- if (background == null) {
- Log.w(TAG, "Background not created");
- } else {
- canvas.drawBitmap(background, 0, 0, backgroundPaint);
- }
- }
- private void fa( Canvas canvas, String text, Paint p, float x, float y ) {
- Path mTextOutlinePath = new Path();
- // adjust the x,y text origin to your personal needs
- p.getTextPath(text, 0, text.length(), x /* getPaddingLeft() */, y /* getBaseline() */, mTextOutlinePath);
- canvas.drawPath(mTextOutlinePath, p);
- // canvas.drawPath(mTextOutlinePath, mStrokePaint);
- }
- private void drawScale(Canvas canvas) {
- // Draw the circle
- canvas.drawOval(scaleRect, scalePaint);
- for (int i = 0; i <= totalNotches; ++i) {
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.rotate(degreeOkMinValue + 90 + degreesPerNotch * i, 0.5f * getWidth(), 0.5f * getHeight());
- float y1 = scaleRect.top;
- float y2 = y1 - 0.015f * getHeight();
- float y3 = y1 - 0.025f * getHeight();
-
- int value = notchToValue(i);
- if (i % (incrementPerLargeNotch/incrementPerSmallNotch) == 0) {
- /* if (value >= scaleMinValue && value <= scaleMaxValue) { */
- // draw a nick
- canvas.drawLine(0.5f * getWidth(), y1, 0.5f * getWidth(), y3, scalePaint);
- String valueString = Integer.toString(value);
- canvas.drawText(valueString, 0.5f * getWidth(), y3 - 0.015f * getWidth(), scalePaint);
- /* } */
- }
- else{
- /* if (value >= scaleMinValue && value <= scaleMaxValue) { */
- // draw a nick
- canvas.drawLine(0.5f * getWidth(), y1, 0.5f * getWidth(), y2, scalePaint);
- /* } */
- }
- canvas.restore();
- }
- }
-
- private void drawScaleRanges(Canvas canvas) {
- canvas.drawArc(rangeRect, degreeMinValue, degreeMaxValue - degreeMinValue, false, rangeAllPaint);
- canvas.drawArc(rangeRect, degreeOkMinValue, degreeOkMaxValue - degreeOkMinValue, false, rangeOkPaint);
- canvas.drawArc(rangeRect, degreeWarningMinValue, degreeWarningMaxValue - degreeWarningMinValue, false, rangeWarningPaint);
- canvas.drawArc(rangeRect, degreeErrorMinValue, degreeErrorMaxValue - degreeErrorMinValue, false, rangeErrorPaint);
- }
- private void drawTitle(Canvas canvas) {
- // Use a vertical offset when printing the upper title. The upper and lower title
- // use the same rectangular but the spacing between the title and the ranges
- // is not equal for the upper and lower title and therefore, the upper title is
- // moved downwards.
- canvas.drawTextOnPath(upperTitle, upperTitlePath, 0.0f, 0.02f * getHeight(), upperTitlePaint);
- canvas.drawTextOnPath(lowerTitle, lowerTitlePath, 0.0f, 0.0f, lowerTitlePaint);
- canvas.drawTextOnPath(unitTitle, unitPath, 0.0f, 0.0f, unitPaint);
- }
- int centerx, centery;
- private void drawHand(Canvas canvas) {
- if (true || dialInitialized) {
- float angle = valueToAngle(currentValue );
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.rotate(angle, centerx, centery);
- canvas.drawPath(handPath, handPaint);
- canvas.restore();
-
- canvas.drawCircle(0.5f * getWidth() , 0.5f * getHeight() , 0.01f * getWidth(), handScrewPaint);
- }
- }
-
- private void drawGauge(Canvas canvas) {
- if (dialInitialized) {
- // When currentValue is not rotated, the tip of the hand points
- // to n -90 degrees.
- float angle = valueToAngle(currentValue) - 90;
-
- if(targetValue <= rangeOkMaxValue){
- canvas.drawArc(valueRect, degreeMinValue, angle - degreeMinValue, false, valueOkPaint);
- }
- if((targetValue > rangeOkMaxValue) && (targetValue <= rangeWarningMaxValue)){
- canvas.drawArc(valueRect, degreeMinValue, degreeOkMaxValue - degreeMinValue, false, valueOkPaint);
- canvas.drawArc(valueRect, degreeWarningMinValue, angle - degreeWarningMinValue, false, valueWarningPaint);
- }
- if((targetValue > rangeWarningMaxValue) && (targetValue <= rangeErrorMaxValue)){
- canvas.drawArc(valueRect, degreeMinValue, degreeOkMaxValue - degreeMinValue, false, valueOkPaint);
- canvas.drawArc(valueRect, degreeWarningMinValue, degreeWarningMaxValue - degreeWarningMinValue, false, valueWarningPaint);
- canvas.drawArc(valueRect, degreeErrorMinValue, angle - degreeErrorMinValue, false, valueErrorPaint);
- }
- }
- }
- private void drawBezel(Canvas canvas) {
- // Draw the bevel in which the value is draw.
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.drawArc(valueRect, degreeMinValue, degreeMaxValue - degreeMinValue, false, valueAllPaint);
- canvas.restore();
- }
- /* Translate a notch to a value for the scale.
- * The notches are evenly spread across the scale, half of the notches on the left hand side
- * and the other half on the right hand side.
- * The raw value calculation uses a constant so that each notch represents a value n + 2.
- */
- private int notchToValue(int notch) {
- //int rawValue = ((notch < totalNotches / 2) ? notch : (notch - totalNotches)) * incrementPerSmallNotch;
- //int shiftedValue = rawValue + scaleCenterValue;
- //return shiftedValue;
-
- return notch * ( scaleMaxValue - scaleMinValue ) / totalNotches;
- }
-
- private float valueToAngle(float value) {
- // scaleCenterValue represents an angle of -90 degrees.
- //return (value - scaleCenterValue) / 2.0f * degreesPerNotch;
- // jaja
- float frac = ( value - scaleMinValue ) / ( scaleMaxValue - scaleMinValue );
- return angleMinValue + frac * ( angleMaxValue - angleMinValue );
- //return degreeOkMinValue - ( value / scaleMaxValue ) * ( degreeOkMinValue + 90 );
- }
- private float valueToAngle2(float value) {
- // scaleCenterValue represents an angle of -90 degrees.
- // return (value - scaleCenterValue) / 2.0f * degreesPerNotch;
- return valueToAngle(value);
- //return degreeOkMinValue - ( value / scaleMaxValue ) * 2 * ( degreeOkMinValue + 90 );
- }
- // Canvas backgroundCanvas ;
- @Override
- protected void onDraw(Canvas canvas) {
- drawBackground(canvas);
- // Draw the needle using the updated value
- if (showHand){
- drawHand( canvas );
- }
- // Calculate a new current value.
- calculateCurrentValue();
- }
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // Log.d(TAG, "Size changed to " + w + "x" + h);
- initDrawingTools();
- regenerateBackground();
- centerx = w / 2;
- centery = h / 2;
- }
-
- private void regenerateBackground() {
- // free the old bitmap
- if (background != null) {
- background.recycle();
- }
-
- background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
- Canvas backgroundCanvas = new Canvas(background);
- drawRim(backgroundCanvas);
- drawFace(backgroundCanvas);
- drawScale(backgroundCanvas);
- if (showRange){
- drawScaleRanges(backgroundCanvas);
- }
- if (showGauge) {
- drawBezel(backgroundCanvas);
- }
- drawTitle(backgroundCanvas);
- }
- // Move the hand slowly to the new position.
- private void calculateCurrentValue() {
- if (!(Math.abs(currentValue - targetValue) > 0.01f)) {
- return;
- }
-
- if (lastDialMoveTime != -1L) {
- long currentTime = System.currentTimeMillis();
- float delta = (currentTime - lastDialMoveTime) / 1000.0f;
- float direction = Math.signum(dialVelocity);
- if (Math.abs(dialVelocity) < 90.0f) {
- dialAcceleration = 5.0f * (targetValue - currentValue);
- } else {
- dialAcceleration = 0.0f;
- }
- currentValue += dialVelocity * delta;
- dialVelocity += dialAcceleration * delta;
- if ((targetValue - currentValue) * direction < 0.01f * direction) {
- currentValue = targetValue;
- dialVelocity = 0.0f;
- dialAcceleration = 0.0f;
- lastDialMoveTime = -1L;
- } else {
- lastDialMoveTime = System.currentTimeMillis();
- }
- invalidate();
- } else {
- lastDialMoveTime = System.currentTimeMillis();
- calculateCurrentValue();
- }
- }
-
- public void setValue(float value) {
- if (value < scaleMinValue) value = scaleMinValue;
- else if (value > scaleMaxValue) value = scaleMaxValue;
- targetValue = value;
- dialInitialized = true;
-
- invalidate(); // forces onDraw() to be called.
- }
- public float getValue() {
- return targetValue;
- }
- }
|