下面列出了怎么用android.graphics.Path.Direction的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
protected void onBoundsChange(Rect bounds) {
if(mBackgroundDrawable != null)
mBackgroundDrawable.setBounds(bounds);
mBackgroundBounds.set(bounds.left + mMask.left, bounds.top + mMask.top, bounds.right - mMask.right, bounds.bottom - mMask.bottom);
mBackground.reset();
switch (mMask.type) {
case Mask.TYPE_OVAL:
mBackground.addOval(mBackgroundBounds, Direction.CW);
break;
case Mask.TYPE_RECTANGLE:
mBackground.addRoundRect(mBackgroundBounds, mMask.cornerRadius, Direction.CW);
break;
}
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
rimRadius = Math.min(bounds.width(), bounds.height()) / 2f - rimPaint.getStrokeWidth();
faceRadius = rimRadius - rimPaint.getStrokeWidth();
screwRadius = rimPaint.getStrokeWidth() * 2;
float hourHandLength = (float) (0.5 * faceRadius);
float minuteHandLength = (float) (0.7 * faceRadius);
float top = bounds.centerY() - screwRadius;
hourHandPath.reset();
hourHandPath.moveTo(bounds.centerX(), bounds.centerY());
hourHandPath.addRect(bounds.centerX(), top, bounds.centerX(), top - hourHandLength, Direction.CCW);
hourHandPath.close();
minuteHandPath.reset();
minuteHandPath.moveTo(bounds.centerX(), bounds.centerY());
minuteHandPath.addRect(bounds.centerX(), top, bounds.centerX(), top - minuteHandLength, Direction.CCW);
minuteHandPath.close();
}
/**
* Sets the bitmap to be used for the zoomed view.
*/
public void setBitmap(Bitmap bitmap) {
if (mZoomedBitmap != null) {
mZoomedBitmap.recycle();
mZoomedBitmap = null;
}
mZoomedBitmap = bitmap;
// Round the corners of the bitmap so it doesn't stick out around the overlay.
Canvas canvas = new Canvas(mZoomedBitmap);
Path path = new Path();
RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
float overlayCornerRadius = getOverlayCornerRadius(getContext());
path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
canvas.clipPath(path, Op.XOR);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
clearPaint.setColor(Color.TRANSPARENT);
canvas.drawPaint(clearPaint);
}
@Override
protected void onBoundsChange(Rect bounds) {
if(mBackgroundDrawable != null)
mBackgroundDrawable.setBounds(bounds);
mBackgroundBounds.set(bounds.left + mMask.left, bounds.top + mMask.top, bounds.right - mMask.right, bounds.bottom - mMask.bottom);
mBackground.reset();
switch (mMask.type) {
case Mask.TYPE_OVAL:
mBackground.addOval(mBackgroundBounds, Direction.CW);
break;
case Mask.TYPE_RECTANGLE:
mBackground.addRoundRect(mBackgroundBounds, mMask.cornerRadius, Direction.CW);
break;
}
}
private void updatePath(final int w, final int h) {
final float maxAbsSize = Math.min(w, h) / 2f;
final float absSize = size < maxSize ? maxAbsSize * size / maxSize
: maxAbsSize - 1;
path.reset();
if (progress == 0) {
path.close();
} else if (progress < maxProgress) {
final float angle = progress * 360 / maxProgress;
final float x = w / 2f;
final float y = h / 2f;
path.moveTo(x, y);
path.arcTo(new RectF(x - absSize, y - absSize, x + absSize, y
+ absSize), 270, angle);
path.close();
} else {
path.addCircle(w / 2f, h / 2f, absSize, Direction.CW);
}
}
/**
* Sets the bitmap to be used for the zoomed view.
*/
public void setBitmap(Bitmap bitmap) {
if (mZoomedBitmap != null) {
mZoomedBitmap.recycle();
mZoomedBitmap = null;
}
mZoomedBitmap = bitmap;
// Round the corners of the bitmap so it doesn't stick out around the overlay.
Canvas canvas = new Canvas(mZoomedBitmap);
Path path = new Path();
RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
float overlayCornerRadius = getOverlayCornerRadius(getContext());
path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
canvas.clipPath(path, Op.XOR);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
clearPaint.setColor(Color.TRANSPARENT);
canvas.drawPaint(clearPaint);
}
/**
* Sets the bitmap to be used for the zoomed view.
*/
public void setBitmap(Bitmap bitmap) {
if (mZoomedBitmap != null) {
mZoomedBitmap.recycle();
mZoomedBitmap = null;
}
mZoomedBitmap = bitmap;
// Round the corners of the bitmap so it doesn't stick out around the overlay.
Canvas canvas = new Canvas(mZoomedBitmap);
Path path = new Path();
RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
float overlayCornerRadius = getOverlayCornerRadius(getContext());
path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
canvas.clipPath(path, Op.XOR);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
clearPaint.setColor(Color.TRANSPARENT);
canvas.drawPaint(clearPaint);
}
private void draw(Canvas c, Paint p, int x, int dir, int top, int bottom, int size) {
sBulletPath.reset();
sBulletPath.addCircle(0.0f, 0.0f, size, Direction.CW);
c.save();
c.translate(x + dir * size, (top + bottom) / 2.0f);
c.drawPath(sBulletPath, p);
c.restore();
}
private void draw(Canvas c, Paint p, int x, int dir, int top, int bottom, int size) {
sBulletPath.reset();
sBulletPath.addCircle(0.0f, 0.0f, size, Direction.CW);
c.save();
c.translate(x + dir * size, (top + bottom) / 2.0f);
c.drawPath(sBulletPath, p);
c.restore();
}
@Override
protected void onDraw(Canvas canvas) {
final float width = canvas.getWidth();
final float height = canvas.getHeight();
mPath.rewind();
mPath.addRoundRect(new RectF(PADDING, PADDING, width - PADDING, height - PADDING), CORNER_RADIUS, CORNER_RADIUS, Direction.CW);
mPath.addPath(mBubbleLegPrototype, renderBubbleLegMatrix(width, height));
canvas.drawPath(mPath, mPaint);
canvas.scale((width - STROKE_WIDTH) / width, (height - STROKE_WIDTH) / height, width / 2f, height / 2f);
canvas.drawPath(mPath, mFillPaint);
}
private void plotMemoryUsage() {
path.reset();
int textWidth = (int) getPaint().measureText(getText().toString());
int availableWidth = getMeasuredWidth() - textWidth - getPaddingLeft() - getPaddingRight();
if (availableWidth < MIN_PIXELS_FOR_GRAPH || memSnapshots.isEmpty()) {
// don't show chart
return;
}
int startX = textWidth + getPaddingLeft() + PLOT_MARGIN;
int availableHeight = getMeasuredHeight() / 2;
int startY = availableHeight;
path.moveTo(startX, startY);
float prevPercentage = 0;
byte index = 0;
for (long snapshot : memSnapshots) {
index++;
float percentage = snapshot / (float) maxMemoryInBytes;
float x = startX + (availableWidth / (float) memSnapshots.size()) * index;
float amplificationFactor = 1;
// exaggerate differences to see the change in the chart
if (prevPercentage > percentage) {
amplificationFactor = 5f;
} else if (prevPercentage < percentage) {
amplificationFactor = .2f;
}
float y = startY - (percentage * availableHeight) * amplificationFactor;
prevPercentage = percentage;
path.lineTo(x, y);
path.addCircle(x, y, 4, Direction.CCW);
}
System.out.println("marian path");
}
private void invalidateRevealInfo() {
if (STRATEGY == CLIP_PATH) {
revealPath.rewind();
if (revealInfo != null) {
revealPath.addCircle(
revealInfo.centerX, revealInfo.centerY, revealInfo.radius, Direction.CW);
}
}
view.invalidate();
}
/**
* Writes the given {@link ShapeAppearanceModel} to {@code path}
*
* @param shapeAppearanceModel The shape to be applied in the path.
* @param interpolation the desired interpolation.
* @param bounds the desired bounds for the path.
* @param pathListener the path
* @param path the returned path out-var.
*/
@RestrictTo(Scope.LIBRARY_GROUP)
public void calculatePath(
ShapeAppearanceModel shapeAppearanceModel,
float interpolation,
RectF bounds,
PathListener pathListener,
@NonNull Path path) {
path.rewind();
overlappedEdgePath.rewind();
boundsPath.rewind();
boundsPath.addRect(bounds, Direction.CW);
ShapeAppearancePathSpec spec =
new ShapeAppearancePathSpec(
shapeAppearanceModel, interpolation, bounds, pathListener, path);
// Calculate the transformations (rotations and translations) necessary for each edge and
// corner treatment.
for (int index = 0; index < 4; index++) {
setCornerPathAndTransform(spec, index);
setEdgePathAndTransform(index);
}
for (int index = 0; index < 4; index++) {
appendCornerPath(spec, index);
appendEdgePath(spec, index);
}
path.close();
overlappedEdgePath.close();
// Union with the edge paths that had an intersection to handle overlaps.
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && !overlappedEdgePath.isEmpty()) {
path.op(overlappedEdgePath, Op.UNION);
}
}
private void updateShapeMask(int width, int height) {
destination.set(
getPaddingLeft(),
getPaddingTop(),
width - getPaddingRight(),
height - getPaddingBottom());
pathProvider.calculatePath(shapeAppearanceModel, 1f /*interpolation*/, destination, path);
// Remove path from rect to draw with clear paint.
maskPath.rewind();
maskPath.addPath(path);
// Do not include padding to clip the background too.
maskRect.set(0, 0, width, height);
maskPath.addRect(maskRect, Direction.CCW);
}
private void draw(Canvas c, Paint p, int x, int dir, int top, int bottom, int size) {
sBulletPath.reset();
sBulletPath.addCircle(0.0f, 0.0f, size, Direction.CW);
c.save();
c.translate(x + dir * size, (top + bottom) / 2.0f);
c.drawPath(sBulletPath, p);
c.restore();
}
public void drawLeadingMargin(Canvas canvas, Paint paint, int x, int dir,
int top, int baseline, int bottom, CharSequence text,
int start, int end, boolean first, Layout layout) {
if (((Spanned)text).getSpanStart(this) == start) {
Style style = paint.getStyle();
paint.setStyle(Style.FILL);
float yPosition;
if (layout != null) {
int line = layout.getLineForOffset(start);
yPosition = (float)layout.getLineBaseline(line) - (float)this.bulletRadius * 2.0F;
} else {
yPosition = (float)(top + bottom) / 2.0F;
}
float xPosition = (float)(x + dir * this.bulletRadius);
if (canvas.isHardwareAccelerated()) {
if (this.mBulletPath == null) {
this.mBulletPath = new Path();
this.mBulletPath.addCircle(0.0F, 0.0F, (float)this.bulletRadius, Direction.CW);
}
canvas.save();
canvas.translate(xPosition, yPosition);
canvas.drawPath(this.mBulletPath, paint);
canvas.restore();
} else {
canvas.drawCircle(xPosition, yPosition, (float)this.bulletRadius, paint);
}
paint.setStyle(style);
}
}
@Override
protected Path newPath() {
Path resultPath = ObjectPool.pathPool.checkOut();
if (!hasRoundedCorners()) {
resultPath.addRect(bounds, Direction.CW);
} else {
resultPath.addRoundRect(bounds, new float[] { radiusTopLeft.width,
radiusTopLeft.height, radiusTopRight.width, radiusTopRight.height,
radiusBottomRight.width, radiusBottomRight.height, radiusBottomLeft.width,
radiusBottomLeft.height }, Direction.CW);
}
return resultPath;
}
@Override
protected Path newPath() {
Path path = ObjectPool.pathPool.checkOut();
RectF rect = new RectF(center.x - radiusX, center.y - radiusY, center.x + radiusX, center.y
+ radiusY);
path.addOval(rect, Direction.CW);
return path;
}
@Override
protected void onBoundsChange(Rect bounds) {
mBackgroundBounds.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
mBackground.reset();
mBackground.addRect(mBackgroundBounds, Direction.CW);
}
private void initRoundRectPath() {
this.roundPath.reset();
RectF rectF = new RectF();
rectF.set(0, 0, this.getWidth(), this.getHeight());
roundPath.addRoundRect(rectF, BlurBehindView.this.cornerRadius, BlurBehindView.this.cornerRadius, Direction.CCW);
}
public void initCirclePath() {
this.circlePath.reset();
this.circlePath.addCircle((float) (this.getWidth() / 2), (float) (this.getHeight() / 2), Math.min((float) this.getWidth(), (float) (this.getHeight() / 2) * BlurBehindView.this.clipCircleRadius), Direction.CCW);
}
public void addCircle(float x, float y, float w) {
this.path.addCircle(x, y, (w / 2f), Direction.CW);
this.pathEmpty = false;
}
public void addRectangle(float x, float y, float width, float height) {
this.path.addRect(x, y, x + width, y + height, Direction.CW);
this.pathEmpty = false;
}
@SuppressWarnings("nullness:argument.type.incompatible")
private void drawMenuBorder(Canvas canvas) {
toolTipView.getGlobalVisibleRect(toolTipRect, null);
menuContentView.getGlobalVisibleRect(menuRect, null);
// Draw the border around the main menu content. Since the actual menu will be drawn after this,
// the section of the border between the menu and the tool tip will be hidden.
borderPath.reset();
borderPath.addRoundRect(
menuRect.left - STROKE_WIDTH,
menuRect.top - STROKE_WIDTH,
menuRect.right + STROKE_WIDTH,
menuRect.bottom + STROKE_WIDTH,
cornerRadius,
cornerRadius,
Direction.CW);
// Get the location of the tooltip's bottom left and right corners and its pointed tip.
int toolTipTop = toolTipRect.top - STROKE_WIDTH;
int toolTipBottom = toolTipRect.bottom + STROKE_WIDTH;
int toolTipLeft = toolTipRect.left - STROKE_WIDTH;
int toolTipRight = toolTipRect.right + STROKE_WIDTH;
Point toolTipPoint = new Point();
Point toolTipFlatEdgeLeftCorner = new Point();
Point toolTipFlatEdgeRightCorner = new Point();
if (toolTipLeft < menuRect.left) {
// Tooltip points left.
toolTipPoint.set(toolTipLeft, toolTipRect.centerY());
toolTipFlatEdgeLeftCorner.set(toolTipRight, toolTipBottom);
toolTipFlatEdgeRightCorner.set(toolTipRight, toolTipTop);
} else if (toolTipRight > menuRect.right) {
// Tooltip points right.
toolTipPoint.set(toolTipRight, toolTipRect.centerY());
toolTipFlatEdgeLeftCorner.set(toolTipLeft, toolTipTop);
toolTipFlatEdgeRightCorner.set(toolTipLeft, toolTipBottom);
} else if (toolTipTop < menuRect.top) {
// Tooltip points up.
toolTipPoint.set(toolTipRect.centerX(), toolTipTop);
toolTipFlatEdgeLeftCorner.set(toolTipLeft, toolTipBottom);
toolTipFlatEdgeRightCorner.set(toolTipRight, toolTipBottom);
} else {
// Tooltip points down
toolTipPoint.set(toolTipRect.centerX(), toolTipBottom);
toolTipFlatEdgeLeftCorner.set(toolTipLeft, toolTipTop);
toolTipFlatEdgeRightCorner.set(toolTipRight, toolTipTop);
}
// Draw the border around the menu tool tip. In a triangle pointing upwards, this draws from the
// bottom left corner to the pointed tip of the triangle, back down to the bottom right corner.
borderPath.moveTo(toolTipFlatEdgeLeftCorner.x, toolTipFlatEdgeLeftCorner.y);
borderPath.lineTo(toolTipPoint.x, toolTipPoint.y);
borderPath.lineTo(toolTipFlatEdgeRightCorner.x, toolTipFlatEdgeRightCorner.y);
canvas.drawPath(borderPath, menuBorderPaint);
}
public void draw(GUIDrawingArea drawarea, Canvas canvas) {
//first-press arrow and release arrow boxes
int start_rect_top = drawarea.timeToY(start_time);
//int start_rect_bottom = start_rect_top + Tools.button_h;
int end_rect_top = drawarea.timeToY(end_time);
int end_rect_bottom = end_rect_top + Tools.button_h;
int rect_left = drawarea.pitchToX(pitch);
int rect_right = rect_left + Tools.button_w;
int win_h = canvas.getHeight();
//int win_w = canvas.getWidth();
boolean fallingDown = start_rect_top > end_rect_top;
int hold_rect_top, hold_rect_bottom; //bounding box for hold rectangle
int hold_draw_start, hold_draw_end, hold_draw_add; // parameters to draw loop
if (fallingDown) { //arrows falling down
hold_rect_top = end_rect_top + Tools.button_h/2;
hold_rect_bottom = start_rect_top + Tools.button_h/2;
hold_draw_start = drawarea.timeToY(original_starttime) + Tools.button_h / 2 - holdimg_h;
hold_draw_end = ((end_rect_top > 0) ? end_rect_top : 0) - holdimg_h;
hold_draw_add = -holdimg_h;
} else { //arrows rising up
hold_rect_top = start_rect_top + Tools.button_h/2;
hold_rect_bottom = end_rect_top + Tools.button_h/2;
hold_draw_start = drawarea.timeToY(original_starttime) + Tools.button_h / 2;
hold_draw_end = ((end_rect_bottom < win_h) ? end_rect_bottom : win_h);
hold_draw_add = holdimg_h;
}
//body
Path path = new Path();
//TODO diagonal clip paths for up/down arrows (straight for left/right)
path.addRect(rect_left, hold_rect_top, rect_right, hold_rect_bottom, Direction.CCW);
canvas.clipPath(path, Op.INTERSECT);
//need to swap comparison direction based on motion direction, hence xor
for (int y = hold_draw_start; (y <= hold_draw_end) ^ fallingDown; y += hold_draw_add) {
canvas.drawBitmap(
drawarea.getBitmap(
holdRsrc(mode, false),
Tools.button_w, holdimg_h
),
rect_left, y, null);
}
drawarea.setClip_arrowSpace(canvas);
//end arrow (top)
canvas.drawBitmap(
drawarea.getBitmap(
holdRsrc(mode, true),
Tools.button_w, Tools.button_h
),
rect_left, end_rect_top, null
);
//start arrow (bottom)
canvas.drawBitmap(
drawarea.getBitmap(
GUINoteImage.rsrc(pitch, fraction, clicked),
Tools.button_w, Tools.button_h
),
rect_left, start_rect_top, null
);
//debug
/*Paint p = new Paint();
switch (mode) {
case INACTIVE: p.setARGB(127, 0, 255, 0); break;
case ACTIVE: p.setARGB(200, 0, 255, 0); break;
case DEAD: p.setARGB(127, 127, 127, 127); break;
}
canvas.drawRect(new Rect(rect_left, end_rect_top, rect_right, start_rect_bottom), p);*/
}
@Override
protected void onBoundsChange(Rect bounds) {
mBackgroundBounds.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
mBackground.reset();
mBackground.addRect(mBackgroundBounds, Direction.CW);
}
@Override
protected Path newPath() {
Path path = ObjectPool.pathPool.checkOut();
path.addCircle(center.x, center.y, radius, Direction.CW);
return path;
}
public void layout(int left, int top, int right, int bottom) {
mClipPath.reset();
mClipPath.addCircle((right - left) / 2, (bottom - top) / 2, mFabRadius, Direction.CW);
}
private void drawBubblePath(Canvas canvas) {
Rect bounds = new Rect();
getDrawingRect(bounds);
float top = bounds.top;
float bottom = bounds.bottom;
float right = (this.bubbleBeak == 1) ? bounds.right - padding : bounds.right;
float left = (this.bubbleBeak == 0) ? bounds.left + padding : bounds.left;
path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(left, top + radius);
if (bubbleBeak == 1) {
// right
if (bubbleBeakVertical == 1) {
// upper right beak
path.arcTo(new RectF(left, top, left + (radius * 2), top + (radius * 2)), 180, 90);
path.arcTo(new RectF(right - (radius * 2), top, right, top + (radius * 2)), 270, 35);
path.cubicTo(right - 10, top + 3, right - 10, top + 2, right + (padding), top);
path.cubicTo(right - 2, top + (radius / 4), right, top + (radius / 4), right, top + radius);
path.arcTo(new RectF(right - (radius * 2), top, right, top + (radius * 2)), 355, 5);
path.arcTo(new RectF(right - (radius * 2), bottom - (radius * 2), right, bottom), 0, 90);
path.arcTo(new RectF(left, bottom - (radius * 2), left + (radius * 2), bottom), 90, 90);
} else {
// lower right beak
path.arcTo(new RectF(left, top, left + (radius * 2), top + (radius * 2)), 180, 90);
path.arcTo(new RectF(right - (radius * 2), top, right, top + (radius * 2)), 270, 90);
path.arcTo(new RectF(right - (radius * 2), bottom - (radius * 2), right, bottom), 0, 5);
path.cubicTo(right - 2, bottom - (radius / 4), right, bottom - (radius / 4), right + (padding), bottom);
path.cubicTo(right - 10, bottom - 3, right - 10, bottom - 2, right - (radius / 2),
bottom - (radius / 5));
path.arcTo(new RectF(right - (radius * 2), bottom - (radius * 2), right, bottom), 55, 35);
path.arcTo(new RectF(left, bottom - (radius * 2), left + (radius * 2), bottom), 90, 90);
}
} else if (bubbleBeak == 0) {
// left
if (bubbleBeakVertical == 1) {
// upper left beak
path.arcTo(new RectF(left, top, left + (radius * 2), top + (radius * 2)), 175, 5);
path.cubicTo(left + 2, top + (radius / 4), left, top + (radius / 4), left - (padding), top);
path.cubicTo(left + 10, top + 3, left + 10, top + 2, left + (radius / 2), top + (radius / 5));
path.arcTo(new RectF(left, top, left + (radius * 2), top + (radius * 2)), 235, 35);
path.arcTo(new RectF(right - (radius * 2), top, right, top + (radius * 2)), 270, 90);
path.arcTo(new RectF(right - (radius * 2), bottom - (radius * 2), right, bottom), 0, 90);
path.arcTo(new RectF(left, bottom - (radius * 2), left + (radius * 2), bottom), 90, 90);
} else {
// lower left beak
path.arcTo(new RectF(left, top, left + (radius * 2), top + (radius * 2)), 180, 90);
path.arcTo(new RectF(right - (radius * 2), top, right, top + (radius * 2)), 270, 90);
path.arcTo(new RectF(right - (radius * 2), bottom - (radius * 2), right, bottom), 0, 90);
path.arcTo(new RectF(left, bottom - (radius * 2), left + (radius * 2), bottom), 90, 35);
path.cubicTo(left + 10, bottom - 3, left + 10, bottom - 2, left - (padding), bottom);
path.cubicTo(left + 2, bottom - (radius / 4), left, bottom - (radius / 4), left, bottom - radius);
path.arcTo(new RectF(left, bottom - (radius * 2), left + (radius * 2), bottom), 175, 5);
}
} else if (bubbleBeak == 2) {
// none
path.addRoundRect(new RectF(left, top, right, bottom), radius, radius, Direction.CCW);
}
path.close();
}
public static void addEllipse(Path path, float x, float y, float w, float h)
{
path.addOval(new RectF(x, y, x + w, y + h), Direction.CW);
}