Last active
August 29, 2015 14:22
-
-
Save Tagakov/55e9481a7cb41a14faf7 to your computer and use it in GitHub Desktop.
Example of clipPath like behavior with use of hardware accelerated Xfermode.
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
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