Last active
February 1, 2016 21:09
-
-
Save hrules6872/cadbd4094d35ee541e5a to your computer and use it in GitHub Desktop.
Improved DisplayLeakConnectorView extracted from LeakCanary library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class DisplayLeakConnectorView extends View { | |
private static final float DEFAULT_STROKEWIDTH = 4f; | |
private static final int DEFAULT_COLOR_BRANCH = 0xFFbababa; | |
private static final int DEFAULT_COLOR_ROOT = 0xFF84a6c5; | |
private static final int DEFAULT_COLOR_LEAK = 0xFFb1554e; | |
public static final int TYPE_START = -1; | |
public static final int TYPE_NODE = 0; | |
public static final int TYPE_END = 1; | |
public static final int TYPE_DEFAULT = TYPE_NODE; | |
@Retention(RetentionPolicy.SOURCE) @IntDef({ TYPE_START, TYPE_NODE, TYPE_END }) | |
public @interface DisplayLeakConnectorViewType { | |
} | |
private Paint paintBranch; | |
private Paint paintRoot; | |
private Paint paintLeak; | |
private Paint paintClear; | |
private int type; | |
private float strokeSize; | |
private Bitmap cache; | |
public DisplayLeakConnectorView(Context context) { | |
this(context, null); | |
} | |
public DisplayLeakConnectorView(Context context, AttributeSet attrs) { | |
this(context, attrs, 0); | |
} | |
public DisplayLeakConnectorView(Context context, AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
init(); | |
} | |
@TargetApi(Build.VERSION_CODES.LOLLIPOP) | |
public DisplayLeakConnectorView(Context context, AttributeSet attrs, int defStyleAttr, | |
int defStyleRes) { | |
super(context, attrs, defStyleAttr, defStyleRes); | |
init(); | |
} | |
private void init() { | |
strokeSize = dpToPixel(DEFAULT_STROKEWIDTH, getResources()); | |
type = getConnectorViewType(TYPE_DEFAULT); | |
paintBranch = new Paint(Paint.ANTI_ALIAS_FLAG); | |
paintBranch.setColor(DEFAULT_COLOR_BRANCH); | |
paintBranch.setStrokeWidth(strokeSize); | |
paintRoot = new Paint(Paint.ANTI_ALIAS_FLAG); | |
paintRoot.setColor(DEFAULT_COLOR_ROOT); | |
paintRoot.setStrokeWidth(strokeSize); | |
paintLeak = new Paint(Paint.ANTI_ALIAS_FLAG); | |
paintLeak.setColor(DEFAULT_COLOR_LEAK); | |
paintClear = new Paint(Paint.ANTI_ALIAS_FLAG); | |
paintClear.setColor(Color.TRANSPARENT); | |
paintClear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); | |
} | |
private @DisplayLeakConnectorViewType int getConnectorViewType(int value) { | |
return value; | |
} | |
public @DisplayLeakConnectorViewType int getType() { | |
return type; | |
} | |
public void setType(@DisplayLeakConnectorViewType int type) { | |
if (type != this.type) { | |
this.type = type; | |
invalidate(); | |
} | |
} | |
public float getStrokeSize() { | |
return paintRoot.getStrokeWidth(); | |
} | |
public void setStrokeSize(float strokeSize) { | |
paintRoot.setStrokeWidth(strokeSize); | |
invalidate(); | |
} | |
public int getRootColor() { | |
return paintRoot.getColor(); | |
} | |
public void setRootColor(@ColorInt int rootColor) { | |
paintRoot.setColor(rootColor); | |
invalidate(); | |
} | |
public int getBranchColor() { | |
return paintBranch.getColor(); | |
} | |
public void setBranchColor(@ColorInt int branchColor) { | |
paintBranch.setColor(branchColor); | |
invalidate(); | |
} | |
public int getLeakColor() { | |
return paintLeak.getColor(); | |
} | |
public void setLeakColor(@ColorInt int leakColor) { | |
paintLeak.setColor(leakColor); | |
invalidate(); | |
} | |
@Override protected void onDraw(Canvas canvas) { | |
int width = getWidth(); | |
int height = getHeight(); | |
if (cache != null && (cache.getWidth() != width || cache.getHeight() != height)) { | |
cache.recycle(); | |
cache = null; | |
} | |
if (cache == null) { | |
cache = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); | |
Canvas cacheCanvas = new Canvas(cache); | |
float halfWidth = width / 2f; | |
float halfHeight = height / 2f; | |
float thirdWidth = width / 3f; | |
switch (type) { | |
case TYPE_START: | |
float radiusClear = halfWidth - strokeSize / 2f; | |
cacheCanvas.drawRect(0, 0, width, radiusClear, paintRoot); | |
cacheCanvas.drawCircle(0, radiusClear, radiusClear, paintClear); | |
cacheCanvas.drawCircle(width, radiusClear, radiusClear, paintClear); | |
cacheCanvas.drawLine(halfWidth, 0, halfWidth, halfHeight, paintRoot); | |
cacheCanvas.drawLine(halfWidth, halfHeight, halfWidth, height, paintBranch); | |
cacheCanvas.drawCircle(halfWidth, halfHeight, halfWidth, paintBranch); | |
cacheCanvas.drawCircle(halfWidth, halfHeight, thirdWidth, paintClear); | |
break; | |
case TYPE_NODE: | |
cacheCanvas.drawLine(halfWidth, 0, halfWidth, height, paintBranch); | |
cacheCanvas.drawCircle(halfWidth, halfHeight, halfWidth, paintBranch); | |
cacheCanvas.drawCircle(halfWidth, halfHeight, thirdWidth, paintClear); | |
break; | |
default: | |
cacheCanvas.drawLine(halfWidth, 0, halfWidth, halfHeight, paintBranch); | |
cacheCanvas.drawCircle(halfWidth, halfHeight, thirdWidth, paintLeak); | |
break; | |
} | |
} | |
canvas.drawBitmap(cache, 0, 0, null); | |
} | |
@Override public void invalidate() { | |
if (cache != null) { | |
cache.recycle(); | |
cache = null; | |
} | |
super.invalidate(); | |
} | |
private float dpToPixel(float dp, Resources resources) { | |
DisplayMetrics metrics = resources.getDisplayMetrics(); | |
return metrics.density * dp; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment