Catalogue of series articles
Android custom view using PathEffect to achieve dynamic effects
The article finally has the source code
preface
In the last article of this type, the offset is changed to achieve dynamic effect. The method used is drawArc. This article still changes the offset and uses the subclass of PathEffect.
design sketch:
1, First, introduce some subclasses of PathEffect
-
CornerPathEffect: connect the included angle between the connecting segments of Path in a smoother way, similar to the effect of arc and tangent. The radius parameter specifies the radius of the arc.
-
DashPathEffect: dashes the line segment of Path. The intervals are an array of ON and OFF dashed lines. The number of elements in the array needs to be > = 2; phase is the offset when drawing.
-
DiscretePathEffect: scatters the line segments of the Path, resulting in a scattering effect based on the original Path. segmentLength specifies the maximum segment length, and deviation is the deviation during drawing.
-
PathDashPathEffect: use the Path graph to fill the current Path. shape refers to the filling graph, advance is the interval between each graph, and phase is the offset when drawing., style is the free enumeration value of this class. There are three cases: ROTATE, MORPH and TRANSLATE. In the case of ROTATE: the graphics at the segment connection are converted to ROTATE to an angle consistent with the moving direction of the next segment. MORPH case: the drawing will be connected to the next segment with deformation such as tension or compression. In the case of TRANSLATE: the drawing will be connected to the next segment by position translation.
-
ComposePathEffect: combining effects
-
SumPathEffect: the superposition effect is different from ComposePathEffect. The effects of the two parameters will be displayed independently during performance, and then the two effects will be simply overlapped and displayed together
2, Look at some specific code of subclasses
private static void makeEffects(PathEffect[] e, float phase) { e[0] = null; // No effect e[1] = new CornerPathEffect(30);//CornerPathEffect e[2] = new DashPathEffect(new float[] {10, 5, 5, 5}, phase);//DashPathEffect e[3] = new PathDashPathEffect(makePathDash(), 12, phase, PathDashPathEffect.Style.ROTATE);//PathDashPathEffect e[4] = new ComposePathEffect(e[2], e[1]);//ComposePathEffect e[5] = new ComposePathEffect(e[3], e[1]);//ComposePathEffect }
3, Case realization (CornerPathEffect, PathDashPathEffect, ComposePathEffect)
The effect is the e[5] of the upper sequence code. The corner patheffect is used to realize the arc effect, and the focus is PathDashPathEffect.
There are several parameters in PathDashPathEffect:
new PathDashPathEffect(makePathDash(), 12, phase, PathDashPathEffect.Style.ROTATE);
The first parameter is the small path graph. In the case, the blogger draws a diamond:
private static Path makePathDash() { Path p = new Path(); p.moveTo(0, 0); p.lineTo(4, 4); p.lineTo(8, 0); p.lineTo(4, -4); p.moveTo(0, 0); return p; }
The second parameter is the interval between each graph.
The third parameter is the deviation during drawing
The fourth parameter is style. The blogger selects ROTATE: the graphics at the connection of line segments are converted to ROTATE to an angle consistent with the moving direction of the next segment.
Finally, ComposePathEffect is used for combination.
Draw motion path
private static Path makeFollowPath() { Path p = new Path(); p.moveTo(0, 0); p.lineTo(400,0); p.lineTo(400,400); p.lineTo(0,400); p.lineTo(0,0); return p; }
Modify the offset to achieve dynamic effect
mPhase += 1; invalidate();
Four source code
public class SampleView extends View { private Paint mPaint; private Path mPath; private PathEffect[] mEffects; private int mColors; private float mPhase; private static void makeEffects(PathEffect[] e, float phase) { e[0] = null; e[1] = new CornerPathEffect(30); e[2] = new DashPathEffect(new float[] {10, 5, 5, 5}, phase); e[3] = new PathDashPathEffect(makePathDash(), 12, phase, PathDashPathEffect.Style.ROTATE); e[4] = new SumPathEffect(e[3], e[1]); e[5] = new ComposePathEffect(e[3], e[1]); } public SampleView(Context context) { super(context); setFocusable(true); setFocusableInTouchMode(true); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(6); mPath = makeFollowPath(); //Initialize PathEffect [] mEffects = new PathEffect[6]; mColors = Color.BLACK; } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.WHITE); RectF bounds = new RectF(); mPath.computeBounds(bounds, false); canvas.translate(10 - bounds.left, 10 - bounds.top); makeEffects(mEffects, mPhase); mPhase += 1; invalidate(); //Select style mPaint.setPathEffect(mEffects[5]); mPaint.setColor(mColors); canvas.drawPath(mPath, mPaint); canvas.translate(0, 28); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: mPath = makeFollowPath(); return true; } return super.onKeyDown(keyCode, event); } //Draw running path private static Path makeFollowPath() { Path p = new Path(); p.moveTo(0, 0); p.lineTo(400,0); p.lineTo(400,400); p.lineTo(0,400); p.lineTo(0,0); return p; } //Draw small icons for running private static Path makePathDash() { Path p = new Path(); p.moveTo(0, 0); p.lineTo(4, 4); p.lineTo(8, 0); p.lineTo(4, -4); p.moveTo(0, 0); return p; } }