onDraw代码如下:
@Override
protected void onDraw(Canvas canvas) {
final ArrayList<Cell> pattern = mPattern;
final int count = pattern.size();
final boolean[][] drawLookup = mPatternDrawLookup;
if (mPatternDisplayMode == DisplayMode.Animate) {
// figure out which circles to draw
// + 1 so we pause on complete pattern
final int oneCycle = (count + 1) * MILLIS_PER_CIRCLE_ANIMATING;
final int spotInCycle = (int) (SystemClock.elapsedRealtime() -
mAnimatingPeriodStart) % oneCycle;
final int numCircles = spotInCycle / MILLIS_PER_CIRCLE_ANIMATING;
clearPatternDrawLookup();
for (int i = 0; i < numCircles; i++) {
final Cell cell = pattern.get(i);
drawLookup[cell.getRow()][cell.getColumn()] = true;
}
// figure out in progress portion of ghosting line
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.column);
final float centerY = getCenterYForRow(currentCell.row);
final Cell nextCell = pattern.get(numCircles);
final float dx = percentageOfNextCircle *
(getCenterXForColumn(nextCell.column) - centerX);
final float dy = percentageOfNextCircle *
(getCenterYForRow(nextCell.row) - centerY);
mInProgressX = centerX + dx;
mInProgressY = centerY + dy;
}
// TODO: Infinite loop here...
invalidate();
}
final Path currentPath = mCurrentPath;
currentPath.rewind();
// draw the circles
for (int i = 0; i < 3; i++) {
float centerY = getCenterYForRow(i);
for (int j = 0; j < 3; j++) {
CellState cellState = mCellStates[i][j];
float centerX = getCenterXForColumn(j);
float translationY = cellState.translationY;
if (isHardwareAccelerated() && cellState.hwAnimating) {
DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
cellState.hwRadius, cellState.hwPaint);
} else {
drawCircle(canvas, (int) centerX, (int) centerY + translationY,
cellState.radius, drawLookup[i][j], cellState.alpha);
}
}
}
// TODO: the path should be created and cached every time we hit-detect a cell
// only the last segment of the path should be computed here
// draw the path of the pattern (unless we are in stealth mode)
final boolean drawPath = !mInStealthMode;
if (drawPath) {
mPathPaint.setColor(getCurrentColor(true /* partOfPattern */));
boolean anyCircles = false;
float lastX = 0f;
float lastY = 0f;
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 (!drawLookup[cell.row][cell.column]) {
break;
}
anyCircles = true;
float centerX = getCenterXForColumn(cell.column);
float centerY = getCenterYForRow(cell.row);
if (i != 0) {
CellState state = mCellStates[cell.row][cell.column];
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
currentPath.lineTo(state.lineEndX, state.lineEndY);
} else {
currentPath.lineTo(centerX, centerY);
}
canvas.drawPath(currentPath, mPathPaint);
}
lastX = centerX;
lastY = centerY;
}
// draw last in progress section
if ((mPatternInProgress || mPatternDisplayMode == DisplayMode.Animate)
&& anyCircles) {
currentPath.rewind();
currentPath.moveTo(lastX, lastY);
currentPath.lineTo(mInProgressX, mInProgressY);
mPathPaint.setAlpha((int) (calculateLastSegmentAlpha(
mInProgressX, mInProgressY, lastX, lastY) * 255f));
canvas.drawPath(currentPath, mPathPaint);
}
}
} 这部分代码比较长,这里就不细细分析了,主要流程就是:判断当前显示模式是否是正在绘制。如果是,保存连接的点的状态,计算手指当前所在的点坐标;如果不是,进入第2步。
根据1中保存的状态,绘制选中的点,已更改选中的点的样式。
选中的点和未选中的点的状态都是在这部分实时完成的,通过遍历9个点,根据1中保存的状态改变画笔属性绘制不同的样式。
绘制连接线(path)。主要是获得路径,然后drawPath。
最后就是onTouchEvent处理手指ACTION事件,包括ACTION_DOWN、ACTION_UP、ACTION_MOVE、ACTION_CANCEL事件。每种事件,判断手势绘制是否结束、改变显示模式、刷新View、回调方法。



京公网安备 11010502036488号