Skip to content

Instantly share code, notes, and snippets.

@Tagakov
Last active August 29, 2015 14:22
Show Gist options
  • Save Tagakov/55e9481a7cb41a14faf7 to your computer and use it in GitHub Desktop.
Save Tagakov/55e9481a7cb41a14faf7 to your computer and use it in GitHub Desktop.
Example of clipPath like behavior with use of hardware accelerated Xfermode.
package com.tagakov.testapplication;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
/**
* Created by tagakov on 28.05.15.
*/
public class SectorClipProgress extends View implements ValueAnimator.AnimatorUpdateListener {
private BitmapDrawable foregroundDrawable;
private final RectF rectF = new RectF();
private final Rect rect = new Rect();
private final PorterDuffXfermode srcInXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
private final ValueAnimator valueAnimator = ValueAnimator.ofFloat();
private Paint paint;
private float sweepAngle;
public SectorClipProgress(Context context, int backgroundResource, int foregroundResource) {
super(context);
init(backgroundResource, foregroundResource);
}
public SectorClipProgress(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public SectorClipProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SectorClipProgress(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
private void init(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.SectorClipProgress);
foregroundDrawable = (BitmapDrawable) a.getDrawable(R.styleable.SectorClipProgress_foreground);
a.recycle();
initPaint();
}
private void init(int backgroundResource, int foregroundResource) {
setBackgroundResource(backgroundResource);
foregroundDrawable = (BitmapDrawable) getResources().getDrawable(foregroundResource);
initPaint();
}
private void initPaint() {
if (foregroundDrawable != null) {
paint = foregroundDrawable.getPaint();
} else {
throw new IllegalStateException("You should provide foreground drawable for SectorClipProgress view!");
}
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(this);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
getDrawingRect(rect);
rectF.set(rect);
}
@Override
protected void onDraw(Canvas canvas) {
int saveCount = canvas.saveLayer(rectF, null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawArc(rectF, -90, sweepAngle, true, paint);
Xfermode oldMode = paint.getXfermode();
paint.setXfermode(srcInXferMode);
foregroundDrawable.setBounds(rect);
foregroundDrawable.draw(canvas);
paint.setXfermode(oldMode);
canvas.restoreToCount(saveCount);
}
public void start(int duration) {
if (valueAnimator.isRunning())
valueAnimator.cancel();
valueAnimator.setDuration(duration);
valueAnimator.setFloatValues(0f, 360f);
valueAnimator.start();
}
public void stop() {
if (valueAnimator.isRunning()) {
valueAnimator.cancel();
valueAnimator.setFloatValues(sweepAngle, 0);
valueAnimator.setDuration(300);
valueAnimator.start();
}
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
sweepAngle = (float) animation.getAnimatedValue();
invalidate();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment