@Override
    protected void onDraw(Canvas canvas) {
        final int width = getWidth();
        final int height = getHeight();

        // Draw everything smaller to account for drawing the curve and animated object
        // outside the 1x1 grid
        canvas.translate(width * (1 - SCALE_FACTOR) / 2, height * (1 - SCALE_FACTOR) / 2);
        canvas.scale(SCALE_FACTOR, SCALE_FACTOR);

        // Draw horizontal/vertical lines
        for (int i = 0; i <= 100; i += 10) {
            float percentage = (float) i / 100;
            float x = percentage * width;
            float y = percentage * height;
            canvas.drawLine(0, y, width, y, mGridPaint);
            canvas.drawLine(x, 0, x, height, mGridPaint);
        }

        // Draw the interpolator's timing curve
        float lastX = 0;
        float lastY = mInterpolator.getInterpolation(0);
        for (float x = 0; x <= 1f; x += .01f) {
            float y = mInterpolator.getInterpolation(x);
            canvas.drawLine(lastX * width, height - (height * lastY),
                    width * x, height - (height * y), mCurvePaint);
            lastX = x;
            lastY = y;
        }

        // Draw control point(s) for the Path when a PathInterpolator is set
        if (mCubicPath || mQuadraticPath) {
            float cx1Pixels = getWidth() * mCx1;
            float cy1Pixels = getHeight() * (1 - mCy1);
            canvas.drawCircle(cx1Pixels, cy1Pixels, RADIUS * 1.4f, mControlPointPaint);
            if (mCubicPath) {
                float cx2Pixels = getWidth() * mCx2;
                float cy2Pixels = getHeight() * (1 - mCy2);
                canvas.drawCircle(cx2Pixels, cy2Pixels, RADIUS * 1.4f, mControlPointPaint);
            }
        }

        // Draw ball position given the current animation fraction
        float fractionY = mInterpolator.getInterpolation(mFraction);
        float centerX = getWidth() * mFraction;
        float centerY = getHeight() * (1 - fractionY);
        canvas.drawCircle(centerX, centerY, RADIUS, mBallPaint);
    }
This override allows the control points for PathInterpolators to be moved by the
user, by dragging them into new positions.

{@inheritDoc}
AnimationsInterpolatorPlayground/app/src/main/java/com/example/android/interpolatorplayground/CurveVisualizer.java