I am inspired by the the new Material Design animations and I worked to create a similar drawable that is used in new support v7 Action Bar Drawer Toggle.
I created a CustomDrawable. All I actually did is that I created a Play triangle on canvas and pause logo on the left of the left margin of the visible canvas. I rotate the canvas according to the progress and restore it. Then I used Xfermode to crop the rotated result into a circle.
I cant find the solution to the problem.
The problem is that the xFermode is not applied to the 180 degree rotated result(after calling canvas.restore()).
Here is the code of Activity.
public class MainActivity extends Activity{
ImageView iv;
CustomDrawable drawable = new CustomDrawable();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
iv = (ImageView) findViewById(R.id.button);
iv.setLayerType(View.LAYER_TYPE_HARDWARE, null);
iv.setBackgroundDrawable(drawable);
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
float[] values = { 0, 1 };
if (drawable.getProgress() != 0) {
values[0] = drawable.getProgress();
values[1] = 0;
}
ObjectAnimator animator = ObjectAnimator.ofFloat(drawable,
"progress", values);
animator.setDuration(2000);
animator.start();
}
});
}
}
And the code for the CustomDrawable
public class CustomDrawable extends Drawable {
private float mProgress = 0;
private Paint mPaint = new Paint();
private Path mPath = new Path();
private final float rootTwo = (float) Math.sqrt(2);
private final float rootThree = (float) Math.sqrt(3);
private float radius = 0;
private float side = 0;
private Point[] triangle = new Point[3];
Paint xferpaint = new Paint();
Canvas cropper;
Bitmap bitmap;
Interpolator interpolator = new AnticipateOvershootInterpolator();
private float width;
Rect rec1, rec2;
public CustomDrawable() {
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.FILL);
xferpaint.setColor(Color.RED);
xferpaint.setStyle(Style.FILL);
xferpaint.setAntiAlias(true);
}
@Override
public void draw(Canvas canvas) {
canvas.getClipBounds(bound);
boundsf.set(bound);
if (radius == 0) {
radius = Math.min(bound.centerX(), bound.centerY());
radius -= 5;
bitmap = Bitmap.createBitmap(bound.width(), bound.height(),
Config.ARGB_8888);
cropper = new Canvas(bitmap);
cropper.drawCircle(bound.centerX(), bound.centerY(), radius,
xferpaint);
xferpaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
side = rootTwo * radius;
triangle[0] = new Point(
(int) (bound.centerX() + (side / rootThree)),
bound.centerY());
triangle[1] = new Point(bound.centerX()
- (int) (side / (2 * rootThree)), bound.centerY()
- (int) (side / 2));
triangle[2] = new Point(bound.centerX()
- (int) (side / (2 * rootThree)), bound.centerY()
+ (int) (side / 2));
width = side / 4;
rec1 = new Rect((int) (-bound.centerX() - (3 * width / 2)),
(int) (bound.centerY() - (side / 2)),
(int) (-bound.centerX() - (width / 2)),
(int) (bound.centerY() + (side / 2)));
rec2 = new Rect((int) (-bound.centerX() + (width / 2)),
(int) (bound.centerY() - (side / 2)),
(int) (-bound.centerX() + (3 * width / 2)),
(int) (bound.centerY() + (side / 2)));
}
mPath.rewind();
mPath.moveTo(triangle[0].x, triangle[0].y);
mPath.lineTo(triangle[1].x, triangle[1].y);
mPath.lineTo(triangle[2].x, triangle[2].y);
mPath.close();
mPaint.setColor(Color.parseColor("#378585"));
canvas.drawPaint(mPaint);
mPaint.setColor(Color.parseColor("#FF0400"));
canvas.rotate(180 * interpolator.getInterpolation(mProgress), 0,
bound.centerY());
canvas.drawPath(mPath, mPaint);
canvas.drawRect(rec1, mPaint);
canvas.drawRect(rec2, mPaint);
canvas.restore();
canvas.drawBitmap(bitmap, 0, 0, xferpaint);
}
@Override
public int getOpacity() {
return mPaint.getAlpha();
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter filter) {
mPaint.setColorFilter(filter);
}
public float getProgress() {
return mProgress;
}
public void setProgress(float progress) {
mProgress = progress;
invalidateSelf();
}
}