Source code
package android.support.v7.graphics.drawable;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.appcompat.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public class DrawerArrowDrawable extends Drawable {
public static final int ARROW_DIRECTION_END = 3;
public static final int ARROW_DIRECTION_LEFT = 0;
public static final int ARROW_DIRECTION_RIGHT = 1;
public static final int ARROW_DIRECTION_START = 2;
private static final float ARROW_HEAD_ANGLE = ((float) Math.toRadians(45.0d));
private float mArrowHeadLength;
private float mArrowShaftLength;
private float mBarGap;
private float mBarLength;
private int mDirection = 2;
private float mMaxCutForBarSize;
private final Paint mPaint = new Paint();
private final Path mPath = new Path();
private float mProgress;
private final int mSize;
private boolean mSpin;
private boolean mVerticalMirror = false;
@Retention(RetentionPolicy.SOURCE)
public @interface ArrowDirection {
}
public DrawerArrowDrawable(Context context) {
this.mPaint.setStyle(Style.STROKE);
this.mPaint.setStrokeJoin(Join.MITER);
this.mPaint.setStrokeCap(Cap.BUTT);
this.mPaint.setAntiAlias(true);
TypedArray a = context.getTheme().obtainStyledAttributes(null, R.styleable.DrawerArrowToggle, R.attr.drawerArrowStyle, R.style.Base_Widget_AppCompat_DrawerArrowToggle);
setColor(a.getColor(R.styleable.DrawerArrowToggle_color, 0));
setBarThickness(a.getDimension(R.styleable.DrawerArrowToggle_thickness, 0.0f));
setSpinEnabled(a.getBoolean(R.styleable.DrawerArrowToggle_spinBars, true));
setGapSize((float) Math.round(a.getDimension(R.styleable.DrawerArrowToggle_gapBetweenBars, 0.0f)));
this.mSize = a.getDimensionPixelSize(R.styleable.DrawerArrowToggle_drawableSize, 0);
this.mBarLength = (float) Math.round(a.getDimension(R.styleable.DrawerArrowToggle_barLength, 0.0f));
this.mArrowHeadLength = (float) Math.round(a.getDimension(R.styleable.DrawerArrowToggle_arrowHeadLength, 0.0f));
this.mArrowShaftLength = a.getDimension(R.styleable.DrawerArrowToggle_arrowShaftLength, 0.0f);
a.recycle();
}
public void setArrowHeadLength(float length) {
if (this.mArrowHeadLength != length) {
this.mArrowHeadLength = length;
invalidateSelf();
}
}
public float getArrowHeadLength() {
return this.mArrowHeadLength;
}
public void setArrowShaftLength(float length) {
if (this.mArrowShaftLength != length) {
this.mArrowShaftLength = length;
invalidateSelf();
}
}
public float getArrowShaftLength() {
return this.mArrowShaftLength;
}
public float getBarLength() {
return this.mBarLength;
}
public void setBarLength(float length) {
if (this.mBarLength != length) {
this.mBarLength = length;
invalidateSelf();
}
}
public void setColor(@ColorInt int color) {
if (color != this.mPaint.getColor()) {
this.mPaint.setColor(color);
invalidateSelf();
}
}
@ColorInt
public int getColor() {
return this.mPaint.getColor();
}
public void setBarThickness(float width) {
if (this.mPaint.getStrokeWidth() != width) {
this.mPaint.setStrokeWidth(width);
this.mMaxCutForBarSize = (float) (((double) (width / 2.0f)) * Math.cos((double) ARROW_HEAD_ANGLE));
invalidateSelf();
}
}
public float getBarThickness() {
return this.mPaint.getStrokeWidth();
}
public float getGapSize() {
return this.mBarGap;
}
public void setGapSize(float gap) {
if (gap != this.mBarGap) {
this.mBarGap = gap;
invalidateSelf();
}
}
public void setDirection(int direction) {
if (direction != this.mDirection) {
this.mDirection = direction;
invalidateSelf();
}
}
public boolean isSpinEnabled() {
return this.mSpin;
}
public void setSpinEnabled(boolean enabled) {
if (this.mSpin != enabled) {
this.mSpin = enabled;
invalidateSelf();
}
}
public int getDirection() {
return this.mDirection;
}
public void setVerticalMirror(boolean verticalMirror) {
if (this.mVerticalMirror != verticalMirror) {
this.mVerticalMirror = verticalMirror;
invalidateSelf();
}
}
public void draw(Canvas canvas) {
boolean flipToPointRight;
float f;
float f2;
Rect bounds = getBounds();
switch (this.mDirection) {
case 0:
flipToPointRight = false;
break;
case 1:
flipToPointRight = true;
break;
case 3:
flipToPointRight = DrawableCompat.getLayoutDirection(this) == 0;
break;
default:
if (DrawableCompat.getLayoutDirection(this) != 1) {
flipToPointRight = false;
break;
} else {
flipToPointRight = true;
break;
}
}
float arrowHeadBarLength = lerp(this.mBarLength, (float) Math.sqrt((double) ((this.mArrowHeadLength * this.mArrowHeadLength) * 2.0f)), this.mProgress);
float arrowShaftLength = lerp(this.mBarLength, this.mArrowShaftLength, this.mProgress);
float arrowShaftCut = (float) Math.round(lerp(0.0f, this.mMaxCutForBarSize, this.mProgress));
float rotation = lerp(0.0f, ARROW_HEAD_ANGLE, this.mProgress);
if (flipToPointRight) {
f = 0.0f;
} else {
f = -180.0f;
}
if (flipToPointRight) {
f2 = 180.0f;
} else {
f2 = 0.0f;
}
float canvasRotate = lerp(f, f2, this.mProgress);
float arrowWidth = (float) Math.round(((double) arrowHeadBarLength) * Math.cos((double) rotation));
float arrowHeight = (float) Math.round(((double) arrowHeadBarLength) * Math.sin((double) rotation));
this.mPath.rewind();
float topBottomBarOffset = lerp(this.mBarGap + this.mPaint.getStrokeWidth(), -this.mMaxCutForBarSize, this.mProgress);
float arrowEdge = (-arrowShaftLength) / 2.0f;
this.mPath.moveTo(arrowEdge + arrowShaftCut, 0.0f);
this.mPath.rLineTo(arrowShaftLength - (2.0f * arrowShaftCut), 0.0f);
this.mPath.moveTo(arrowEdge, topBottomBarOffset);
this.mPath.rLineTo(arrowWidth, arrowHeight);
this.mPath.moveTo(arrowEdge, -topBottomBarOffset);
this.mPath.rLineTo(arrowWidth, -arrowHeight);
this.mPath.close();
canvas.save();
float barThickness = this.mPaint.getStrokeWidth();
canvas.translate((float) bounds.centerX(), (float) (((double) ((float) ((((int) ((((float) bounds.height()) - (3.0f * barThickness)) - (this.mBarGap * 2.0f))) / 4) * 2))) + ((((double) barThickness) * 1.5d) + ((double) this.mBarGap))));
if (this.mSpin) {
canvas.rotate(((float) ((this.mVerticalMirror ^ flipToPointRight) != 0 ? -1 : 1)) * canvasRotate);
} else if (flipToPointRight) {
canvas.rotate(180.0f);
}
canvas.drawPath(this.mPath, this.mPaint);
canvas.restore();
}
public void setAlpha(int alpha) {
if (alpha != this.mPaint.getAlpha()) {
this.mPaint.setAlpha(alpha);
invalidateSelf();
}
}
public void setColorFilter(ColorFilter colorFilter) {
this.mPaint.setColorFilter(colorFilter);
invalidateSelf();
}
public int getIntrinsicHeight() {
return this.mSize;
}
public int getIntrinsicWidth() {
return this.mSize;
}
public int getOpacity() {
return -3;
}
@FloatRange(from = 0.0d, to = 1.0d)
public float getProgress() {
return this.mProgress;
}
public void setProgress(@FloatRange(from = 0.0d, to = 1.0d) float progress) {
if (this.mProgress != progress) {
this.mProgress = progress;
invalidateSelf();
}
}
public final Paint getPaint() {
return this.mPaint;
}
private static float lerp(float a, float b, float t) {
return ((b - a) * t) + a;
}
}