package carnero.cgeo; import android.util.AttributeSet; import android.view.View; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.Canvas; import android.graphics.Bitmap; import android.graphics.BitmapFactory; public class cgCompassMini extends View { private int arrowSkin = R.drawable.compass_arrow_mini_white; private Boolean lock = false; private Context context = null; private cgBase base = null; private Double cacheLat = null; private Double cacheLon = null; private Bitmap compassArrow = null; private Double azimuth = new Double(0); private Double heading = new Double(0); private PaintFlagsDrawFilter setfil = null; private PaintFlagsDrawFilter remfil = null; public cgCompassMini(Context contextIn) { super(contextIn); context = contextIn; } public cgCompassMini(Context contextIn, AttributeSet attrs) { super(contextIn, attrs); context = contextIn; TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.cgCompassMini); int usedSkin = attributes.getInt(R.styleable.cgCompassMini_skin, 0); if (usedSkin == 1) arrowSkin = R.drawable.compass_arrow_mini_black; else arrowSkin = R.drawable.compass_arrow_mini_white; } @Override public void onAttachedToWindow() { compassArrow = BitmapFactory.decodeResource(context.getResources(), arrowSkin); setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); } @Override public void onDetachedFromWindow() { if (compassArrow != null) { compassArrow.recycle(); compassArrow = null; } } public void setContent(cgBase baseIn, Double cacheLatIn, Double cacheLonIn) { base = baseIn; cacheLat = cacheLatIn; cacheLon = cacheLonIn; } protected void updateAzimuth(Double azimuthIn) { azimuth = azimuthIn; updateDirection(); } protected void updateHeading(Double headingIn) { heading = headingIn; updateDirection(); } protected void updateCoords(Double latitudeIn, Double longitudeIn) { if (latitudeIn == null || longitudeIn == null || cacheLat == null || cacheLon == null) { return; } heading = cgBase.getHeading(latitudeIn, longitudeIn, cacheLat, cacheLon); updateDirection(); } protected void updateDirection() { if (compassArrow == null || compassArrow.isRecycled() == true) { return; } // compass margins int compassRoseWidth = compassArrow.getWidth(); int compassRoseHeight = compassArrow.getWidth(); int marginLeft = (getWidth() - compassRoseWidth) / 2; int marginTop = (getHeight() - compassRoseHeight) / 2; invalidate(marginLeft, marginTop, (marginLeft + compassRoseWidth), (marginTop + compassRoseHeight)); } @Override protected void onDraw(Canvas canvas){ lock = true; super.onDraw(canvas); Double azimuthRelative = azimuth - heading; if (azimuthRelative < 0) { azimuthRelative = azimuthRelative + 360; } else if (azimuthRelative >= 360) { azimuthRelative = azimuthRelative - 360; } // compass margins canvas.setDrawFilter(setfil); int marginLeft = 0; int marginTop = 0; int compassArrowWidth = compassArrow.getWidth(); int compassArrowHeight = compassArrow.getWidth(); int canvasCenterX = (compassArrowWidth / 2) + ((getWidth() - compassArrowWidth) / 2); int canvasCenterY = (compassArrowHeight / 2) + ((getHeight() - compassArrowHeight) / 2); marginLeft = (getWidth() - compassArrowWidth) / 2; marginTop = (getHeight() - compassArrowHeight) / 2; canvas.rotate(new Float(-(azimuthRelative)), canvasCenterX, canvasCenterY); canvas.drawBitmap(compassArrow, marginLeft, marginTop, null); canvas.rotate(new Float(azimuthRelative), canvasCenterX, canvasCenterY); canvas.setDrawFilter(remfil); lock = false; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = 21 + getPaddingLeft() + getPaddingRight(); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } private int measureHeight(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = 21 + getPaddingTop() + getPaddingBottom(); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } }