@Override
    protected void onDraw(Canvas canvas) {
        final ArrayList<Cell> pattern = mPattern;
        final int count = pattern.size();

        if (patternDisplayMode == DisplayMode.Animate) {

            final int oneCycle = (count + 1) * MILLIS_PER_CIRCLE_ANIMATING;
            final int spotInCycle = (int) (SystemClock.elapsedRealtime() - animatingPeriodStart)
                    % oneCycle;
            final int numCircles = spotInCycle / MILLIS_PER_CIRCLE_ANIMATING;

            clearPatternDrawLookup();
            for (int i = 0; i < numCircles; i++) {
                final Cell cell = pattern.get(i);
                cellManager.draw(cell, true);
            }

            final boolean needToUpdateInProgressPoint = numCircles > 0
                    && numCircles < count;

            if (needToUpdateInProgressPoint) {
                final float percentageOfNextCircle = ((float) (spotInCycle % MILLIS_PER_CIRCLE_ANIMATING))
                        / MILLIS_PER_CIRCLE_ANIMATING;

                final Cell currentCell = pattern.get(numCircles - 1);
                final float centerX = getCenterXForColumn(currentCell.getColumn());
                final float centerY = getCenterYForRow(currentCell.getRow());

                final Cell nextCell = pattern.get(numCircles);
                final float dx = percentageOfNextCircle
                        * (getCenterXForColumn(nextCell.getColumn()) - centerX);
                final float dy = percentageOfNextCircle
                        * (getCenterYForRow(nextCell.getRow()) - centerY);
                inProgressX = centerX + dx;
                inProgressY = centerY + dy;
            }
            invalidate();
        }

        final float squareWidth = this.squareWidth;
        final float squareHeight = this.squareHeight;

        float radius = (squareWidth * diameterFactor * 0.5f);
        pathPaint.setStrokeWidth(radius);

        final Path currentPath = this.currentPath;
        currentPath.rewind();

        // draw the circles
        final int paddingTop = this.paddingTop;
        final int paddingLeft = this.paddingLeft;

        for (int i = 0; i < gridRows; i++) {
            float topY = paddingTop + i * squareHeight;
            for (int j = 0; j < gridColumns; j++) {
                float leftX = paddingLeft + j * squareWidth;
                drawCircle(canvas, (int) leftX, (int) topY, cellManager.isDrawn(i, j));
            }
        }

        // only the last segment of the path should be computed here
        // draw the path of the pattern (unless the user is in progress, and
        // we are in stealth mode)
        final boolean drawPath = (!inStealthMode
                && patternDisplayMode == DisplayMode.Correct || !inErrorStealthMode
                && patternDisplayMode == DisplayMode.Wrong);

        // draw the arrows associated with the path (unless the user is in
        // progress, and
        // we are in stealth mode)
        boolean oldFlagCircle = (circlePaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
        boolean oldFlagDot = (dotPaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
        circlePaint.setFilterBitmap(true);
        dotPaint.setFilterBitmap(true);

        if (drawPath) {
            boolean anyCircles = false;
            for (int i = 0; i < count; i++) {
                Cell cell = pattern.get(i);

                // only draw the part of the pattern stored in
                // the lookup table (this is only different in the case
                // of animation).
                if (!cellManager.isDrawn(cell)) {
                    break;
                }
                anyCircles = true;

                float centerX = getCenterXForColumn(cell.getColumn());
                float centerY = getCenterYForRow(cell.getRow());
                if (i == 0) {
                    currentPath.moveTo(centerX, centerY);
                } else {
                    currentPath.lineTo(centerX, centerY);
                }
            }

            // add last in progress section
            if ((patternInProgress || patternDisplayMode == DisplayMode.Animate)
                    && anyCircles && count > 1) {
                currentPath.lineTo(inProgressX, inProgressY);
            }
            canvas.drawPath(currentPath, pathPaint);
        }

        circlePaint.setFilterBitmap(oldFlagCircle); // restore default flag
        dotPaint.setFilterBitmap(oldFlagDot); // restore default flag
    }
Helper method to find the column x fallis into.

@param x The x coordinate.
@return The column that x falls in, or -1 if it falls in no column.
android-patternview/src/main/java/com/eftimoff/patternview/PatternView.java