下面列出了android.graphics.Path#addRoundRect ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 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
public void draw(Canvas canvas) {
final boolean positionChanged = adapterPositionChanged();
if (rippleOverlay) {
if (!positionChanged) {
rippleBackground.draw(canvas);
}
super.draw(canvas);
if (!positionChanged) {
if (rippleRoundedCorners != 0) {
Path clipPath = new Path();
RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
canvas.clipPath(clipPath);
}
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
} else {
if (!positionChanged) {
rippleBackground.draw(canvas);
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
super.draw(canvas);
}
}
@Override
public void draw(Canvas canvas) {
final boolean positionChanged = adapterPositionChanged();
if (rippleOverlay) {
if (!positionChanged) {
rippleBackground.draw(canvas);
}
super.draw(canvas);
if (!positionChanged) {
if (rippleRoundedCorners != 0) {
Path clipPath = new Path();
RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
canvas.clipPath(clipPath);
}
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
} else {
if (!positionChanged) {
rippleBackground.draw(canvas);
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
super.draw(canvas);
}
}
@Override
public void draw(Canvas canvas) {
final boolean positionChanged = adapterPositionChanged();
if (rippleOverlay) {
if (!positionChanged) {
rippleBackground.draw(canvas);
}
super.draw(canvas);
if (!positionChanged) {
if (rippleRoundedCorners != 0) {
Path clipPath = new Path();
RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
canvas.clipPath(clipPath);
}
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
} else {
if (!positionChanged) {
rippleBackground.draw(canvas);
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
super.draw(canvas);
}
}
private void computePath(Rect bounds) {
final float currentScale = mCurrentScale;
final Path path = mPath;
final RectF rect = mRect;
final Matrix matrix = mMatrix;
path.reset();
int totalSize = Math.min(bounds.width(), bounds.height());
float initial = mClosedStateSize;
float destination = totalSize;
float currentSize = initial + (destination - initial) * currentScale;
float halfSize = currentSize / 2f;
float inverseScale = 1f - currentScale;
float cornerSize = halfSize * inverseScale;
float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize};
rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
path.addRoundRect(rect, corners, Path.Direction.CCW);
matrix.reset();
matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
matrix.postTranslate(0, hDiff);
path.transform(matrix);
}
private void computePath(Rect bounds) {
final float currentScale = mCurrentScale;
final Path path = mPath;
final RectF rect = mRect;
final Matrix matrix = mMatrix;
path.reset();
int totalSize = Math.min(bounds.width(), bounds.height());
float initial = mClosedStateSize;
float currentSize = initial + ((float) totalSize - initial) * currentScale;
float halfSize = currentSize / 2f;
float inverseScale = 1f - currentScale;
float cornerSize = halfSize * inverseScale;
float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize};
rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
path.addRoundRect(rect, corners, Path.Direction.CCW);
matrix.reset();
matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
matrix.postTranslate(0, hDiff);
path.transform(matrix);
}
@Override
public void draw(Canvas canvas) {
final boolean positionChanged = adapterPositionChanged();
if (rippleOverlay) {
if (!positionChanged) {
rippleBackground.draw(canvas);
}
super.draw(canvas);
if (!positionChanged) {
if (rippleRoundedCorners != 0) {
Path clipPath = new Path();
RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
clipPath.addRoundRect(rect, rippleRoundedCorners, rippleRoundedCorners, Path.Direction.CW);
canvas.clipPath(clipPath);
}
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
} else {
if (!positionChanged) {
rippleBackground.draw(canvas);
canvas.drawCircle(currentCoords.x, currentCoords.y, radius, paint);
}
super.draw(canvas);
}
}
private void computePath(Rect bounds) {
final float currentScale = mCurrentScale;
final Path path = mPath;
final RectF rect = mRect;
final Matrix matrix = mMatrix;
path.reset();
int totalSize = Math.min(bounds.width(), bounds.height());
float initial = mClosedStateSize;
float destination = totalSize;
float currentSize = initial + (destination - initial) * currentScale;
float halfSize = currentSize / 2f;
float inverseScale = 1f - currentScale;
float cornerSize = halfSize * inverseScale;
float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize};
rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
path.addRoundRect(rect, corners, Path.Direction.CCW);
matrix.reset();
matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
matrix.postTranslate(0, hDiff);
path.transform(matrix);
}
private void computePath(Rect bounds) {
final float currentScale = mCurrentScale;
final Path path = mPath;
final RectF rect = mRect;
final Matrix matrix = mMatrix;
path.reset();
int totalSize = Math.min(bounds.width(), bounds.height());
float initial = mClosedStateSize;
float destination = totalSize;
float currentSize = initial + (destination - initial) * currentScale;
float halfSize = currentSize / 2f;
float inverseScale = 1f - currentScale;
float cornerSize = halfSize * inverseScale;
float[] corners = new float[]{halfSize, halfSize, halfSize, halfSize, halfSize, halfSize, cornerSize, cornerSize};
rect.set(bounds.left, bounds.top, bounds.left + currentSize, bounds.top + currentSize);
path.addRoundRect(rect, corners, Path.Direction.CCW);
matrix.reset();
matrix.postRotate(-45, bounds.left + halfSize, bounds.top + halfSize);
matrix.postTranslate((bounds.width() - currentSize) / 2, 0);
float hDiff = (bounds.bottom - currentSize - mExternalOffset) * inverseScale;
matrix.postTranslate(0, hDiff);
path.transform(matrix);
}
@Override
public void measuredSize(int width, int height) {
super.measuredSize(width, height);
if(mRadiusArray != null){
mPath = new Path();
mPath.addRoundRect(new RectF(0, 0, width, height), mRadiusArray, Path.Direction.CW);
}
mRect = new RectF(0,0,width,height);
}
@Override
public void measuredSize(int width, int height) {
super.measuredSize(width, height);
if(mRadiusArray != null){
mPath = new Path();
mPath.addRoundRect(new RectF(0, 0, width, height), mRadiusArray, Path.Direction.CW);
}
mRect = new RectF(0,0,width,height);
}
@Override
public void onDraw(Canvas canvas) {
try {
Path clipPath = new Path();
float roundedDp = getResources().getDimension(R.dimen.Card_Radius);
clipPath.addRoundRect(new RectF(canvas.getClipBounds()), roundedDp, roundedDp, Path.Direction.CW);
canvas.clipPath(clipPath);
} catch(Exception e) {
Log.e(TAG, "Failed to clip path on canvas", e);
}
super.onDraw(canvas);
}
@Override
public void update(@NonNull PromptOptions options, float revealModifier,
float alphaModifier)
{
PromptUtils.scale(mBaseBoundsCentre, mBaseBounds, mBounds, revealModifier, true);
mPath = new Path();
mPath.addRoundRect(mBounds, mRx, mRy, Path.Direction.CW);
}
private void prepareBorderPath(int topPadding,
int rightPadding,
int bottomPadding,
int leftPadding,
@NonNull RectF rectF,
@NonNull Path path) {
if (mBorderRadius != null) {
prepareBorderRadius(rectF);
float topLeftRadius = getBorderRadius(mOverlappingBorderRadius, BORDER_TOP_LEFT_RADIUS);
float topRightRadius = getBorderRadius(mOverlappingBorderRadius, BORDER_TOP_RIGHT_RADIUS);
float bottomRightRadius = getBorderRadius(mOverlappingBorderRadius,
BORDER_BOTTOM_RIGHT_RADIUS);
float bottomLeftRadius = getBorderRadius(mOverlappingBorderRadius,
BORDER_BOTTOM_LEFT_RADIUS);
path.addRoundRect(
rectF,
new float[]{
topLeftRadius - leftPadding,
topLeftRadius - topPadding,
topRightRadius - rightPadding,
topRightRadius - topPadding,
bottomRightRadius - rightPadding,
bottomRightRadius - bottomPadding,
bottomLeftRadius - leftPadding,
bottomLeftRadius - bottomPadding
},
Path.Direction.CW);
} else {
path.addRect(rectF, Path.Direction.CW);
}
}
@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;
}
void computeMenuFill() {
if (flyoutMenuView.adapter != null && flyoutMenuView.layout != null && needsComputeMenuFill()) {
Size menuSize = flyoutMenuView.layout.getMinimumSizeForItems(flyoutMenuView.adapter.getCount(), flyoutMenuView.itemWidth, flyoutMenuView.itemHeight, flyoutMenuView.itemMargin);
float buttonRadius = flyoutMenuView.buttonRadius;
float buttonLeft = buttonCenter.x - buttonRadius;
float buttonRight = buttonCenter.x + buttonRadius;
float buttonTop = buttonCenter.y - buttonRadius;
float buttonBottom = buttonCenter.y + buttonRadius;
float leftMin;
float leftMax;
float topMin;
float topMax;
if (flyoutMenuView.horizontalMenuAnchorOutside) {
leftMin = buttonLeft - menuSize.width - flyoutMenuView.menuMargin;
leftMax = buttonRight + flyoutMenuView.menuMargin;
} else {
leftMin = buttonLeft;
leftMax = buttonRight - menuSize.width;
}
if (flyoutMenuView.verticalMenuAnchorOutside) {
topMin = buttonTop - menuSize.height - flyoutMenuView.menuMargin;
topMax = buttonBottom + flyoutMenuView.menuMargin;
} else {
topMin = buttonTop;
topMax = buttonBottom - menuSize.height;
}
int menuLeft = (int) (leftMin + flyoutMenuView.horizontalMenuAnchor * (leftMax - leftMin));
int menuTop = (int) (topMin + flyoutMenuView.verticalMenuAnchor * (topMax - topMin));
// the frame of the menu, when open
menuOpenRect = new RectF(menuLeft, menuTop, menuLeft + menuSize.width, menuTop + menuSize.height);
sanitizeMenuPosition(menuOpenRect);
// the round rect we'll use as clipping mask for the animated fill
menuOpenShapePath = new Path();
menuOpenShapePath.addRoundRect(menuOpenRect, menuBackgroundCornerRadius, menuBackgroundCornerRadius, Path.Direction.CW);
// compute the circular radius to fill the menuOpenShapePath
float a = distanceToButtonCenter(menuOpenRect.left, menuOpenRect.top);
float b = distanceToButtonCenter(menuOpenRect.right, menuOpenRect.top);
float c = distanceToButtonCenter(menuOpenRect.right, menuOpenRect.bottom);
float d = distanceToButtonCenter(menuOpenRect.left, menuOpenRect.bottom);
menuOpenRadius = (int) Math.max(a, Math.max(b, Math.max(c, d)));
}
}
/**
* Adapts a website's icon (e.g. favicon or touch icon) to the Material design style guidelines
* for home screen icons. This involves adding some padding and rounding the corners.
*
* @param context Context used to create the intent.
* @param webIcon The website's favicon or touch icon.
* @return Bitmap Either the touch-icon or the newly created favicon.
*/
@CalledByNative
public static Bitmap createHomeScreenIconFromWebIcon(Bitmap webIcon) {
// getLauncherLargeIconSize() is just a guess at the launcher icon size, and is often
// wrong -- the launcher can show icons at any size it pleases. Instead of resizing the
// icon to the supposed launcher size and then having the launcher resize the icon again,
// just leave the icon at its original size and let the launcher do a single rescaling.
// Unless the icon is much too big; then scale it down here too.
Context context = ContextUtils.getApplicationContext();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int maxInnerSize = Math.round(am.getLauncherLargeIconSize() * MAX_INNER_SIZE_RATIO);
int innerSize = Math.min(maxInnerSize, Math.max(webIcon.getWidth(), webIcon.getHeight()));
int padding = Math.round(ICON_PADDING_RATIO * innerSize);
int outerSize = innerSize + 2 * padding;
Bitmap bitmap = null;
try {
bitmap = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e) {
Log.w(TAG, "OutOfMemoryError while creating bitmap for home screen icon.");
return webIcon;
}
// Draw the web icon with padding around it.
Canvas canvas = new Canvas(bitmap);
Rect innerBounds = new Rect(padding, padding, outerSize - padding, outerSize - padding);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setFilterBitmap(true);
canvas.drawBitmap(webIcon, null, innerBounds, paint);
// Round the corners.
int cornerRadius = Math.round(ICON_CORNER_RADIUS_RATIO * outerSize);
Path path = new Path();
path.setFillType(Path.FillType.INVERSE_WINDING);
RectF innerBoundsF = new RectF(innerBounds);
path.addRoundRect(innerBoundsF, cornerRadius, cornerRadius, Path.Direction.CW);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPath(path, paint);
return bitmap;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Path clipPath = new Path();
float radius = 10.0f;
float padding = radius / 2;
int w = this.getWidth();
int h = this.getHeight();
clipPath.addRoundRect(new RectF(padding, padding, w - padding, h - padding), cornerRadius, cornerRadius, Path.Direction.CW);
canvas.clipPath(clipPath);
canvas.drawRect(mBlock, mBackground);
int[] data = mData.getImageData();
double blockSize = w / Math.sqrt(data.length);
for(int i = 0; i < data.length; i++){
double x = (blockSize * i) % w;
double y = Math.floor((blockSize * i) / w) * blockSize;
RectF rect = new RectF((float)x, (float)y, (float)(x + blockSize),(float) (y + blockSize));
if(data[i] == 2) {
canvas.drawRect(rect, mSpot);
}else if(data[i] == 1){
canvas.drawRect(rect, mColor);
}
}
if(hasShadow){
int shadowColors[] = new int[]{Color.argb(200, 50, 50, 50), Color.argb(100, 0, 0, 0), Color.TRANSPARENT};
float[] positions = new float[]{0.20f, 0.35f, 1f};
LinearGradient shadowGradient = new LinearGradient((w/2), h, (w/2), (float) (h-blockSize), shadowColors, positions, Shader.TileMode.CLAMP);
mShadowPaint.setShader(shadowGradient);
int brightColors[] = new int[]{Color.argb(100, 255, 255, 255), Color.TRANSPARENT};
LinearGradient brightGradient = new LinearGradient((w/2), 0, (w/2), (float) blockSize, brightColors, null, Shader.TileMode.CLAMP);
mBrightPaint.setShader(brightGradient);
canvas.drawRect(mBlock, mShadowPaint);
canvas.drawRect(mBlock, mBrightPaint);
}
}
public static void addRoundedRect(Path path, float x, float y, float w, float h, float rw, float rh, Direction dir)
{
path.addRoundRect(PathUtilties.makeRectF(x, y, w, h),rw, rh, dir);
}
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();
}