下面列出了android.graphics.Canvas#save ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void draw(Canvas canvas, Position position) {
canvas.drawPath(mPath, (flags & SELECTED) != 0
? mSelectedPaint : mBackgroundPaint);
canvas.drawPath(mPath, (flags & SELECTED) != 0
? mSelectedPaint : mOutlinePaint);
if (mView != null) {
int state = canvas.save();
canvas.translate(mView.getLeft(), mView.getTop());
// keep icons "upright" if we get displayed on TOP position
if (position != Position.TOP) {
canvas.rotate(mStart + mSweep / 2 - 270);
} else {
canvas.rotate(mStart + mSweep / 2 - 90);
}
canvas.translate(-mView.getWidth() / 2, -mView.getHeight() / 2);
mView.draw(canvas);
canvas.restoreToCount(state);
}
}
void drawOverscrollHeader(Canvas canvas, Drawable drawable, Rect bounds) {
final int height = drawable.getMinimumHeight();
canvas.save();
canvas.clipRect(bounds);
final int span = bounds.bottom - bounds.top;
if (span < height) {
bounds.top = bounds.bottom - height;
}
drawable.setBounds(bounds);
drawable.draw(canvas);
canvas.restore();
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mPinnedHeaderView != null) {
c.save();
mItemTouchListener.invalidTopAndBottom(mPinnedHeaderOffset);
mClipBounds.top = mRecyclerViewPaddingTop + mHeaderTopMargin;
// 锁定画布绘制范围,记为B
// REVERSE_DIFFERENCE,实际上就是求得的B和A的差集范围,即B-A,只有在此范围内的绘制内容才会被显示
// 因此,只绘制(0,0,parent.getWidth(),belowView.getTop())这个范围,然后画布移动了mPinnedHeaderTop,所以刚好是绘制顶部标签移动的范围
// 低版本不行,换回Region.Op.UNION并集
c.clipRect(mClipBounds, Region.Op.UNION);
c.translate(mRecyclerViewPaddingLeft + mHeaderLeftMargin, mPinnedHeaderOffset + mRecyclerViewPaddingTop + mHeaderTopMargin);
mPinnedHeaderView.draw(c);
c.restore();
}
}
@Override
public void draw(Canvas canvas, Matrix currentMatrix, float currentZoom, float
currentRotateDegrees) {
if (isVisible && bitmap != null) {
canvas.save();
float[] goal = {location.x, location.y};
if (!autoScale) {
currentMatrix.mapPoints(goal);
} else {
canvas.setMatrix(currentMatrix);
}
canvas.drawBitmap(bitmap, goal[0] - bitmap.getWidth() / 2,
goal[1] - bitmap.getHeight() / 2, paint);
canvas.restore();
}
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//外圆
canvas.drawCircle(getViewCenterX(), getViewCenterY(), mOuterRadius, mStrokePaint);
//上方按钮
canvas.drawRect(mBtnRectF, mFillPaint);
canvas.drawRect(mBottomBtnRectF, mFillPaint);
//右侧按钮
canvas.save();
canvas.rotate(45, getViewCenterX(), getViewCenterY());
canvas.drawRect(mBottomBtnRectF, mFillPaint);
canvas.restore();
canvas.translate(0, 20);
}
@Override
protected void dispatchDraw (@NonNull Canvas canvas) {
super.dispatchDraw(canvas);
if (mIsDragging) {
canvas.save();
// Position the drag shadow.
float posY = mTouchY - (float)mDragShadow.getMeasuredHeight() / 2f;
canvas.translate(0, posY);
mDragShadow.draw(canvas);
canvas.restore();
}
}
@Override
public void draw(Canvas canvas) {
canvas.save();
canvas.rotate(mRotation, getBounds().centerX(), getBounds().centerY());
super.draw(canvas);
canvas.restore();
}
@Override protected void onDraw(@NonNull Canvas canvas) {
int saveCount = canvas.save();
if (mEnableDraweeMatrix) {
canvas.concat(mAttacher.getDrawMatrix());
}
super.onDraw(canvas);
canvas.restoreToCount(saveCount);
}
public void onPreDraw(@NonNull Canvas canvas) {
if (isClipping) {
canvas.save();
if (State.equals(clipRotation, 0f)) {
canvas.clipRect(clipRect);
} else {
// Note, that prior Android 4.3 (18) canvas matrix is not correctly applied to
// clip rect, clip rect will be set to its upper bound, which is good enough for us.
canvas.rotate(clipRotation, clipRect.centerX(), clipRect.centerY());
canvas.clipRect(clipRect);
canvas.rotate(-clipRotation, clipRect.centerX(), clipRect.centerY());
}
}
}
private void drawTopEdge(DepthLayout dl, Canvas canvas, float[] src) {
float[] dst = new float[] {
dl.getTopLeft().x, dl.getTopLeft().y, dl.getTopRight().x, dl.getTopRight().y,
dl.getTopRightBack().x, dl.getTopRightBack().y, dl.getTopLeftBack().x, dl.getTopLeftBack().y
};
int count = canvas.save();
matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);
canvas.concat(matrix);
drawRectancle(dl, canvas);
drawShadow(dl.getTopLeft(), dl.getTopRight(), -180f, canvas, dl);
canvas.restoreToCount(count);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mStaticLayout != null){
canvas.save();
canvas.translate(getPaddingLeft(), getPaddingTop());
mStaticLayout.draw(canvas);
canvas.restore();
}
}
void plotBarThick(Canvas c, double[] y_value, double[] x_values, int i_begin, int i_end, double x_inc, Paint linePainter) {
if (tmpLineXY.length < 4*(y_value.length)) {
Log.d(TAG, "plotBar(): new tmpLineXY");
tmpLineXY = new float[4*(y_value.length)];
}
final double minYCanvas = axisY.pixelNoZoomFromV(AnalyzerGraphic.minDB);
int pixelStep = 2; // each bar occupy this virtual pixel
c.save();
matrix.reset();
double extraPixelAlignOffset = 0.0f;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// // There is an shift for Android 4.4, while no shift for Android 2.3
// // I guess that is relate to GL ES acceleration
// if (c.isHardwareAccelerated()) {
// extraPixelAlignOffset = 0.5f;
// }
// }
matrix.setTranslate((float)(-axisX.getShift() * (y_value.length - 1) * pixelStep - extraPixelAlignOffset),
(float)(-axisY.getShift() * axisY.nCanvasPixel));
matrix.postScale((float)(axisX.nCanvasPixel / ((axisX.vMaxInView() - axisX.vMinInView()) / x_inc * pixelStep)), (float)axisY.getZoom());
c.concat(matrix);
// fill interval same as canvas pixel width.
for (int i = i_begin; i < i_end; i++) {
float x = x_values == null ? i * pixelStep : (float)(x_values[i] / x_inc * pixelStep);
float y = (float)axisY.pixelNoZoomFromV(clampDB(y_value[i]));
tmpLineXY[4*i ] = x;
tmpLineXY[4*i+1] = (float)minYCanvas;
tmpLineXY[4*i+2] = x;
tmpLineXY[4*i+3] = y;
}
c.drawLines(tmpLineXY, 4*i_begin, 4*(i_end-i_begin), linePainter);
c.restore();
}
/** Draws the graphics based on the progress indicator's properties and the animation states. */
@Override
public void draw(@NonNull Canvas canvas) {
Rect clipBounds = new Rect();
if (getBounds().isEmpty() || !isVisible() || !canvas.getClipBounds(clipBounds)) {
// Escape if bounds are empty, clip bounds are empty, or currently hidden.
return;
}
canvas.save();
drawingDelegate.adjustCanvas(canvas, progressIndicator, getGrowFraction());
float displayedIndicatorWidth = progressIndicator.getIndicatorWidth() * getGrowFraction();
float displayedRoundedCornerRadius =
progressIndicator.getIndicatorCornerRadius() * getGrowFraction();
// Draws the track first as the bottom layer.
drawingDelegate.fillTrackWithColor(
canvas,
paint,
combinedTrackColor,
0f,
1f,
displayedIndicatorWidth,
displayedRoundedCornerRadius);
// Draws the indicators.
for (int segmentIndex = 0;
segmentIndex < animatorDelegate.segmentColors.length;
segmentIndex++) {
drawingDelegate.fillTrackWithColor(
canvas,
paint,
animatorDelegate.segmentColors[segmentIndex],
animatorDelegate.segmentPositions[2 * segmentIndex],
animatorDelegate.segmentPositions[2 * segmentIndex + 1],
displayedIndicatorWidth,
displayedRoundedCornerRadius);
}
}
@Override
public void drawAppName(Canvas canvas, float fraction, String name, int colorOfAppName,
WidthAndHeightOfView widthAndHeightOfView) {
canvas.save();
int width = widthAndHeightOfView.getWidth();
int height = widthAndHeightOfView.getHeight();
Paint paint = new Paint();
paint.setColor(colorOfAppName);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(50);
canvas.drawText(name, width / 2, height / 2 + 50, paint);
canvas.restore();
}
@Override
public void draw(Canvas c) {
final Rect bounds = getBounds();
final int saveCount = c.save();
c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY());
mRing.draw(c, bounds);
c.restoreToCount(saveCount);
}
/**
* 绘制Boss机体
*
* @param canvas
*/
private void drawBoss(Canvas canvas) {
// 极限状态
if (isLimit) {
int y = (int) (currentFrame * object_height);
canvas.save();
canvas.clipRect(object_x, object_y,
object_x + object_width, object_y + object_height);
canvas.drawBitmap(bossPlane_crazy, object_x, object_y - y,
paint);
canvas.restore();
currentFrame++;
if (currentFrame >= 2) {
currentFrame = 0;
}
}
// 疯狂状态
else if (isCrazy) {
canvas.save();
canvas.clipRect(object_x, object_y,
object_x + object_width, object_y + object_height);
canvas.drawBitmap(bossPlane_crazy, object_x, object_y
- object_height, paint);
canvas.restore();
}
// 愤怒状态
else if (isAnger) {
canvas.save();
canvas.clipRect(object_x, object_y,
object_x + object_width, object_y + object_height);
canvas.drawBitmap(boosPlane, object_x, object_y
- object_height, paint);
canvas.restore();
}
// 普通状态
else {
canvas.save();
canvas.clipRect(object_x, object_y,
object_x + object_width, object_y + object_height);
canvas.drawBitmap(boosPlane, object_x, object_y, paint);
canvas.restore();
}
logic();
shoot(canvas); // 射击
}
/**
* 绘制悬浮组
*
* @param c Canvas
* @param parent RecyclerView
*/
protected void onDrawOverGroup(Canvas c, RecyclerView parent) {
int firstVisiblePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
if (firstVisiblePosition == RecyclerView.NO_POSITION) {
return;
}
Group group = getCroup(firstVisiblePosition);
if (group == null)
return;
String groupTitle = group.toString();
if (TextUtils.isEmpty(groupTitle)) {
return;
}
boolean isRestore = false;
Group nextGroup = getCroup(firstVisiblePosition + 1);
if (nextGroup != null && !group.equals(nextGroup)) {
//说明是当前组最后一个元素,但不一定碰撞了
View child = parent.findViewHolderForAdapterPosition(firstVisiblePosition).itemView;
if (child.getTop() + child.getMeasuredHeight() < mGroupHeight) {
//进一步检测碰撞
c.save();//保存画布当前的状态
isRestore = true;
c.translate(0, child.getTop() + child.getMeasuredHeight() - mGroupHeight);
}
}
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int top = parent.getPaddingTop();
int bottom = top + mGroupHeight;
c.drawRect(left, top, right, bottom, mBackgroundPaint);
float x;
float y = top + mTextBaseLine;
if (isCenter) {
x = parent.getMeasuredWidth() / 2 - getTextX(groupTitle);
} else {
x = mPaddingLeft;
}
c.drawText(groupTitle, x, y, mTextPaint);
if (isRestore) {
//还原画布为初始状态
c.restore();
}
}
@Override
protected void onDraw(Canvas c) {
if (isDismissed || outerCircleCenter == null) return;
if (topBoundary > 0 && bottomBoundary > 0) {
c.clipRect(0, topBoundary, getWidth(), bottomBoundary);
}
if (dimColor != -1) {
c.drawColor(dimColor);
}
int saveCount;
outerCirclePaint.setAlpha(outerCircleAlpha);
if (shouldDrawShadow && outlineProvider == null) {
saveCount = c.save();
{
c.clipPath(outerCirclePath, Region.Op.DIFFERENCE);
drawJitteredShadow(c);
}
c.restoreToCount(saveCount);
}
c.drawCircle(outerCircleCenter[0], outerCircleCenter[1], outerCircleRadius, outerCirclePaint);
targetCirclePaint.setAlpha(targetCircleAlpha);
if (targetCirclePulseAlpha > 0) {
targetCirclePulsePaint.setAlpha(targetCirclePulseAlpha);
c.drawCircle(targetBounds.centerX(), targetBounds.centerY(),
targetCirclePulseRadius, targetCirclePulsePaint);
}
c.drawCircle(targetBounds.centerX(), targetBounds.centerY(),
targetCircleRadius, targetCirclePaint);
saveCount = c.save();
{
c.translate(textBounds.left, textBounds.top);
titlePaint.setAlpha(textAlpha);
if (titleLayout != null) {
titleLayout.draw(c);
}
if (descriptionLayout != null && titleLayout != null) {
c.translate(0, titleLayout.getHeight() + TEXT_SPACING);
descriptionPaint.setAlpha((int) (0.54f * textAlpha));
descriptionLayout.draw(c);
}
}
c.restoreToCount(saveCount);
saveCount = c.save();
{
if (tintedTarget != null) {
c.translate(targetBounds.centerX() - tintedTarget.getWidth() / 2,
targetBounds.centerY() - tintedTarget.getHeight() / 2);
c.drawBitmap(tintedTarget, 0, 0, targetCirclePaint);
} else if (target.icon != null) {
c.translate(targetBounds.centerX() - target.icon.getBounds().width() / 2,
targetBounds.centerY() - target.icon.getBounds().height() / 2);
target.icon.setAlpha(targetCirclePaint.getAlpha());
target.icon.draw(c);
}
}
c.restoreToCount(saveCount);
if (debug) {
drawDebugInformation(c);
}
}
@Override
protected void draw(Canvas canvas, Rect bounds) {
int saveCount = canvas.save();
RectF arcBounds = mTempBounds;
arcBounds.set(bounds);
arcBounds.inset(mStrokeXInset, mStrokeYInset);
mCurrentProgressBounds.set(arcBounds.left, arcBounds.bottom - 2 * mCenterRadius,
arcBounds.right, arcBounds.bottom);
//draw loading drawable
mLoadingDrawable.setBounds((int) arcBounds.centerX() - mLoadingDrawable.getIntrinsicWidth() / 2,
0,
(int) arcBounds.centerX() + mLoadingDrawable.getIntrinsicWidth() / 2,
mLoadingDrawable.getIntrinsicHeight());
mLoadingDrawable.draw(canvas);
//draw progress background
float progressInset = mCenterRadius - mProgressCenterRadius;
RectF progressRect = new RectF(mCurrentProgressBounds);
//sub DEFAULT_STROKE_INTERVAL, otherwise will have a interval between progress background and progress outline
progressRect.inset(progressInset - DEFAULT_STROKE_INTERVAL, progressInset - DEFAULT_STROKE_INTERVAL);
mPaint.setColor(mProgressBgColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(progressRect, mProgressCenterRadius, mProgressCenterRadius, mPaint);
//draw progress
mPaint.setColor(mProgressColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawPath(createProgressPath(mProgress, mProgressCenterRadius, progressRect), mPaint);
//draw leaves
for (int i = 0; i < mLeafHolders.size(); i++) {
int leafSaveCount = canvas.save();
LeafHolder leafHolder = mLeafHolders.get(i);
Rect leafBounds = leafHolder.mLeafRect;
canvas.rotate(leafHolder.mLeafRotation, leafBounds.centerX(), leafBounds.centerY());
mLeafDrawable.setBounds(leafBounds);
mLeafDrawable.draw(canvas);
canvas.restoreToCount(leafSaveCount);
}
//draw progress background outline,
//after drawing the leaves and then draw the outline of the progress background can
//prevent the leaves from flying to the outside
RectF progressOutlineRect = new RectF(mCurrentProgressBounds);
float progressOutlineStrokeInset = (mCenterRadius - mProgressCenterRadius) / 2.0f;
progressOutlineRect.inset(progressOutlineStrokeInset, progressOutlineStrokeInset);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mProgressBgColor);
mPaint.setStrokeWidth(mCenterRadius - mProgressCenterRadius);
canvas.drawRoundRect(progressOutlineRect, mCenterRadius, mCenterRadius, mPaint);
//draw electric fan outline
float electricFanCenterX = arcBounds.right - mCenterRadius;
float electricFanCenterY = arcBounds.bottom - mCenterRadius;
mPaint.setColor(mElectricFanOutlineColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mStrokeWidth);
canvas.drawCircle(arcBounds.right - mCenterRadius, arcBounds.bottom - mCenterRadius,
mCenterRadius - mStrokeWidth / 2.0f, mPaint);
//draw electric background
mPaint.setColor(mElectricFanBgColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(arcBounds.right - mCenterRadius, arcBounds.bottom - mCenterRadius,
mCenterRadius - mStrokeWidth + DEFAULT_STROKE_INTERVAL, mPaint);
//draw electric fan
int rotateSaveCount = canvas.save();
canvas.rotate(mRotation, electricFanCenterX, electricFanCenterY);
mElectricFanDrawable.setBounds((int) (electricFanCenterX - mElectricFanDrawable.getIntrinsicWidth() / 2 * mScale),
(int) (electricFanCenterY - mElectricFanDrawable.getIntrinsicHeight() / 2 * mScale),
(int) (electricFanCenterX + mElectricFanDrawable.getIntrinsicWidth() / 2 * mScale),
(int) (electricFanCenterY + mElectricFanDrawable.getIntrinsicHeight() / 2 * mScale));
mElectricFanDrawable.draw(canvas);
canvas.restoreToCount(rotateSaveCount);
//draw 100% text
if (mScale < 1.0f) {
mPaint.setTextSize(mTextSize * (1 - mScale));
mPaint.setColor(mElectricFanOutlineColor);
Rect textRect = new Rect();
mPaint.getTextBounds(PERCENTAGE_100, 0, PERCENTAGE_100.length(), textRect);
canvas.drawText(PERCENTAGE_100, electricFanCenterX - textRect.width() / 2.0f,
electricFanCenterY + textRect.height() / 2.0f, mPaint);
}
canvas.restoreToCount(saveCount);
}
/**
* 绘制翻起页背面
*
* @param canvas
* @param bitmap
*/
private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {
int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2;
float f1 = Math.abs(i - mBezierControl1.x);
int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2;
float f2 = Math.abs(i1 - mBezierControl2.y);
float f3 = Math.min(f1, f2);
mPath1.reset();
mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);
mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);
mPath1.lineTo(mTouch.x, mTouch.y);
mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);
mPath1.close();
GradientDrawable mFolderShadowDrawable;
int left;
int right;
if (mIsRTandLB) {
left = (int) (mBezierStart1.x - 1);
right = (int) (mBezierStart1.x + f3 + 1);
mFolderShadowDrawable = mFolderShadowDrawableLR;
} else {
left = (int) (mBezierStart1.x - f3 - 1);
right = (int) (mBezierStart1.x + 1);
mFolderShadowDrawable = mFolderShadowDrawableRL;
}
canvas.save();
try {
canvas.clipPath(mPath0);
canvas.clipPath(mPath1, Region.Op.INTERSECT);
} catch (Exception e) {
}
mPaint.setColorFilter(mColorMatrixFilter);
float dis = (float) Math.hypot(mCornerX - mBezierControl1.x,
mBezierControl2.y - mCornerY);
float f8 = (mCornerX - mBezierControl1.x) / dis;
float f9 = (mBezierControl2.y - mCornerY) / dis;
mMatrixArray[0] = 1 - 2 * f9 * f9;
mMatrixArray[1] = 2 * f8 * f9;
mMatrixArray[3] = mMatrixArray[1];
mMatrixArray[4] = 1 - 2 * f8 * f8;
mMatrix.reset();
mMatrix.setValues(mMatrixArray);
mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y);
mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);
canvas.drawBitmap(bitmap, mMatrix, mPaint);
// canvas.drawBitmap(bitmap, mMatrix, null);
mPaint.setColorFilter(null);
canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,
(int) (mBezierStart1.y + mMaxLength));
mFolderShadowDrawable.draw(canvas);
canvas.restore();
}