
Gooey Effect Using Canvas API In Android
2 Years ago, I tried to implement gooey effect using a web way.
Gooey Effect in web uses 3 steps.
- Draw Two Circles.
- Blur the Circles.
- Contrast the Circles.
In Android, However, It didn’t work. I was stuck on the second step. The approach that I used cause too much computation, so it was extremely slow for blurring two circles. But 2 Weeks ago, I watched an awesome YouTube droidcon SF 2017 - Canvas Drawing for Fun and Profit that inspired me and I try again. On YouTube, I got some idea from Drawing doughnut icing part and Today I introduce implementing gooey effect using canvas API in android.
There are also three steps as the web version, though the way different.
- Draw two circle paths.
- Union two paths to one path.
- Change the path to gooey effect path.
At first, I declared some member variables into my custom view called GoogeyEffectView.
public class GooeyEffectView extends View {
private Path mLeftCirclePath;
private Path mRightCirclePath;
private Paint mPaint;
private int mCenterX;
private int mCenterY;
public GooeyEffectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mLeftCirclePath = new Path();
mRightCirclePath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10f);
}
...
}
There are two paths mLeftCirclePath
, mRightCirclePath
that represent left side circle and right side circle on canvas.
mPaint
is set as stork to see obviously each step changes.
Then I set center values in onSizeChanged()
method to draw circles on the center of the screen.
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w/2;
mCenterY = h/2;
initGooeyPath();
}
In initGooeyPath()
method(), Gooey Effect will be build up.
Draw two circle paths.
In initGooeyPath()
method(), I reset paths to redraw circle path in the center of the screen when screen size be changed and overriding onDraw()
method to draw circles on canvas.
public void initGooeyPath() {
mLeftCirclePath.reset();
mRightCirclePath.reset();
final float RADIUS = 100f;
final float GAP = 75f;
mLeftCirclePath.addCircle((mCenterX - GAP), mCenterY, RADIUS, Path.Direction.CW);
mRightCirclePath.addCircle((mCenterX + GAP), mCenterY, RADIUS, Path.Direction.CW);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mLeftCirclePath, mPaint);
canvas.drawPath(mRightCirclePath, mPaint);
}
Union two paths to one path.
In initGooeyPath()
method(), I use Path.Op.UNION
enum to make two paths into one path.
And draw only one path.
public void initGooeyPath() {
mLeftCirclePath.reset();
mRightCirclePath.reset();
final float RADIUS = 100f;
final float GAP = 75f;
mLeftCirclePath.addCircle((mCenterX - GAP), mCenterY, RADIUS, Path.Direction.CW);
mRightCirclePath.addCircle((mCenterX + GAP), mCenterY, RADIUS, Path.Direction.CW);
mLeftCirclePath.op(mRightCirclePath, Path.Op.UNION);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mLeftCirclePath, mPaint);
//canvas.drawPath(mRightCirclePath, mPaint);
}
Change the path to gooey effect path.
Finally, I use PathEffect
to make a gooey effect.
- First, Split the circle path into a specific number of a segment using
DiscretePathEffect
. - Second, Make the segmented circle path into a rounded circle path using
CornerPathEffect
. - Third, Combine two effects to one effect using
ComposePathEffect
And set the effect to the mPaint
using setPathEffect()
method.
public void initGooeyPath() {
mLeftCirclePath.reset();
mRightCirclePath.reset();
final float RADIUS = 100f;
final float GAP = 75f;
mLeftCirclePath.addCircle((mCenterX - GAP), mCenterY, RADIUS, Path.Direction.CW);
mRightCirclePath.addCircle((mCenterX + GAP), mCenterY, RADIUS, Path.Direction.CW);
mLeftCirclePath.op(mRightCirclePath, Path.Op.UNION);
final float SEGMENT_NUM = 20f;
PathMeasure pm = new PathMeasure(mLeftCirclePath, true);
DiscretePathEffect discretePathEffect= new DiscretePathEffect(pm.getLength()/SEGMENT_NUM, 0);
CornerPathEffect cornerPathEffect = new CornerPathEffect(50);
ComposePathEffect pathEffect = new ComposePathEffect(cornerPathEffect, discretePathEffect);
mPaint.setPathEffect( pathEffect);
}
And This is final code.
public class GooeyEffectView extends View {
private Path mLeftCirclePath;
private Path mRightCirclePath;
private Paint mPaint;
private int mCenterX;
private int mCenterY;
public GooeyEffectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mLeftCirclePath = new Path();
mRightCirclePath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10f);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w/2;
mCenterY = h/2;
initGooeyPath();
}
public void initGooeyPath() {
mLeftCirclePath.reset();
mRightCirclePath.reset();
final float RADIUS = 100f;
final float GAP = 75f;
mLeftCirclePath.addCircle((mCenterX - GAP), mCenterY, RADIUS, Path.Direction.CW);
mRightCirclePath.addCircle((mCenterX + GAP), mCenterY, RADIUS, Path.Direction.CW);
mLeftCirclePath.op(mRightCirclePath, Path.Op.UNION);
final float SEGMENT_NUM = 20f;
PathMeasure pm = new PathMeasure(mLeftCirclePath, true);
DiscretePathEffect discretePathEffect= new DiscretePathEffect(pm.getLength()/SEGMENT_NUM, 0);
CornerPathEffect cornerPathEffect = new CornerPathEffect(50);
ComposePathEffect pathEffect = new ComposePathEffect(cornerPathEffect, discretePathEffect);
mPaint.setPathEffect( pathEffect);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mLeftCirclePath, mPaint);
}
}
More Interactive, You just add Animation such as moving the x position of circles like below video.
Or you can add resizing and an elastic Interpolator
to make fascinating like below video.
You can get the full source code of GooeyEffectView
on my GitHub
Thanks for reading the article.