Skip to content

Instantly share code, notes, and snippets.

@robbiemu
Created March 24, 2016 18:42
Show Gist options
  • Save robbiemu/e13e13dd92406c7aee73 to your computer and use it in GitHub Desktop.
Save robbiemu/e13e13dd92406c7aee73 to your computer and use it in GitHub Desktop.
need to refactor this bad boy
package com.example.android.sunshine.app;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by RobertoTomás on 0023, 23/3/2016.
*/
public class WindView extends View {
private static final float GESTURE_THRESHOLD_DIP = 16.0f;
private Bitmap pDirectionArrow;
private Bitmap pCompassRing;
private Drawable pDirectionArrowVector;
private Drawable pCompassRingVector;
private final Paint pSpeedText = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Matrix pMatrix = new Matrix();
private Float pDensity;
private Rect pSpeedTextBoundingRectangle;
private Rect pVectorBoundingRectangle;
private int mForegroundColor;
private int mBackgroundColor;
private int mWindSpeed;
private float mWindOriginDegrees;
public float getWindOriginDegrees() {
return mWindOriginDegrees;
}
public void setWindOriginDegrees(float mWindOriginDegrees) {
this.mWindOriginDegrees = mWindOriginDegrees;
_rotateArrow();
invalidate();
}
public int getForegroundColor() {
return mForegroundColor;
}
/**
* The color expected is the resolved color: `getResources().getcolor(R.color...)`
* @param foregroundColor
*/
public void setForegroundColor(int foregroundColor) {
this.mForegroundColor = foregroundColor;
_changeForegroundColor();
invalidate();
}
private void _changeForegroundColor(){
this.pDirectionArrow = _getBitmap(pDirectionArrowVector, mForegroundColor);
}
public int getBackgroundColor() {
return mBackgroundColor;
}
/**
* The color expected is the resolved color: `getResources().getcolor(R.color...)`
* @param backgroundColor
*/
public void setBackgroundColor(int backgroundColor) {
this.mBackgroundColor = backgroundColor;
_changeBackgroundColor();
invalidate();
}
private void _changeBackgroundColor(){
this.pCompassRing = _getBitmap(pCompassRingVector, mBackgroundColor);
}
public int getWindSpeed() {
return mWindSpeed;
}
public void setWindSpeed(int wind_speed) {
this.mWindSpeed = wind_speed;
invalidate();
}
public String getWindSpeedText (){
return Integer.toString(mWindSpeed) + " km/h";
}
/** Constructors **/
public WindView(Context c){
super(c);
objectHandler(c);
}
public WindView(Context c, AttributeSet attrs) {
super(c, attrs);
objectHandler(c);
}
public WindView(Context c, AttributeSet attrs, int DefaultStyle) {
super(c, attrs, DefaultStyle);
objectHandler(c);
}
public void objectHandler(Context c){
this.mForegroundColor = getResources().getColor(R.color.primary_dark_material_light);
this.mBackgroundColor = getResources().getColor(R.color.primary_material_dark);
this.mWindSpeed = 0;
this.mWindOriginDegrees = 0;
this.pSpeedTextBoundingRectangle = new Rect();
this.pVectorBoundingRectangle = new Rect ();
this.pDensity = getContext().getResources().getDisplayMetrics().density;
this.pCompassRingVector = _getVector(R.drawable.svg_wind_compass_ring);
this.pDirectionArrowVector = _getVector(R.drawable.svg_wind_arrow);
this.pCompassRing = _getBitmap(pCompassRingVector, mBackgroundColor);
this.pDirectionArrow = _getBitmap(pDirectionArrowVector, mForegroundColor);
pSpeedText.setStyle(Paint.Style.FILL);
pSpeedText.setColor(mForegroundColor);
pSpeedText.setAntiAlias(true);
int textSize = (int) (GESTURE_THRESHOLD_DIP * pDensity + 0.5f);
textSize *= pDensity;
pSpeedText.setTextSize(textSize);
pSpeedText.setTextAlign(Paint.Align.LEFT);
Typeface typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD_ITALIC);
pSpeedText.setTypeface(typeface);
}
private Drawable _getVector(int drawableId) {
Drawable vectorDrawable;
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.LOLLIPOP){
vectorDrawable = getResources().getDrawable(drawableId,null);
}else {
vectorDrawable = getResources().getDrawable(drawableId);
}
return vectorDrawable;
}
private Bitmap _getBitmap(Drawable vectorDrawable, int color) {
int h = vectorDrawable.getIntrinsicHeight();
int w = vectorDrawable.getIntrinsicWidth();
if(pVectorBoundingRectangle.isEmpty()){
pVectorBoundingRectangle.set(0,0, w, h);
} else {
h = pVectorBoundingRectangle.height();
w = pVectorBoundingRectangle.width();
//Setting a pixel default if intrinsic height or width is not found , eg a shape drawable
h=h>0?h:96;
w=w>0?w:96;
if ((h != pVectorBoundingRectangle.height()) || (w != pVectorBoundingRectangle.width())) {
// the rectangle was not empty, but still had a 0 width or height value
pVectorBoundingRectangle.set(0,0, w, h);
}
}
vectorDrawable.setBounds(pVectorBoundingRectangle);
// Wrap the drawable so that future tinting calls work
// on pre-v21 devices. Always use the returned drawable.
Drawable wrapDrawable = DrawableCompat.wrap(vectorDrawable);
DrawableCompat.setTint(wrapDrawable.mutate(), color);
wrapDrawable.setBounds(pVectorBoundingRectangle);
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
wrapDrawable.draw(canvas);
return bm;
}
private Matrix _rotateArrow() {
pMatrix.setRotate((180+mWindOriginDegrees)%360, pDirectionArrow.getWidth() / 2, pDirectionArrow.getHeight() / 2);
return pMatrix;
}
private int _measureWidth(int measureSpec) {
int preferred = pCompassRing.getWidth() * 2;
return _getMeasurement(measureSpec, preferred);
}
private int _measureHeight(int measureSpec) {
int preferred = pCompassRing.getHeight() * 2;
return _getMeasurement(measureSpec, preferred);
}
private int _getMeasurement(int measureSpec, int preferred) {
int specSize = MeasureSpec.getSize(measureSpec);
int measurement = 0;
switch(MeasureSpec.getMode(measureSpec)) {
case MeasureSpec.EXACTLY:
// This means the width of this view has been given.
measurement = specSize;
break;
case MeasureSpec.AT_MOST:
// Take the minimum of the preferred size and what
// we were told to be.
measurement = Math.min(preferred, specSize);
break;
default:
measurement = preferred;
break;
}
return measurement;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int renderWidth = _measureWidth(widthMeasureSpec);
int renderHeight = _measureHeight(heightMeasureSpec);
// pCompassRingVector.setWidth(renderWidth);
// pCompassRingVector.setHeight(renderHeight);
// pDirectionArrowVector.setWidth(renderWidth);
// pDirectionArrowVector.setHeight(renderHeight);
pVectorBoundingRectangle.set(0, 0, renderHeight, renderWidth);
pSpeedTextBoundingRectangle.set(0,0, renderHeight/4, renderWidth);
setMeasuredDimension(renderWidth, renderHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(18 * pDensity, 18 * pDensity);
canvas.drawBitmap(pCompassRing, 0, 0, null);
canvas.drawBitmap(pDirectionArrow, _rotateArrow(), null);
String txt = getWindSpeedText();
pSpeedText.getTextBounds(
txt, // text
0, // start
txt.length(), // end
pSpeedTextBoundingRectangle // bounds
);
canvas.drawText(
txt, // Text to draw
canvas.getWidth() / 2, // x
canvas.getHeight() / 2 + Math.abs(pSpeedTextBoundingRectangle.height()) / 2, // y
pSpeedText // Paint
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment