下面列出了android.graphics.Path#op ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static void drawCircleShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds) {
//绘制透明圆
Path circlePath = new Path();
circlePath.addCircle(innerBounds.centerX(), innerBounds.centerY(), Math.min(innerBounds.width() / 2 - 1, innerBounds.height() / 2 - 1), Path.Direction.CCW);
//绘制矩形遮罩
Path rectPath = new Path();
rectPath.addRect(outerBounds, Path.Direction.CW);
if (Build.VERSION.SDK_INT >= 19) {
rectPath.op(circlePath, Path.Op.DIFFERENCE);
canvas.drawPath(rectPath, p);
} else {
canvas.clipPath(circlePath, Region.Op.DIFFERENCE);
canvas.drawPath(rectPath, p);
}
//绘制矩形边框
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(innerBounds, paint);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public ViewOutlineProvider getOutlineProvider() {
shadowpath = new Path();
if (config.getRadius() == 0) {
shadowpath = path;
} else {
rect = new Rect(0, 0, (int) width, (int) height);
RectF r = new RectF(rect);
shadowpath.addRoundRect(r, config.getRadius(), config.getRadius(), Path.Direction.CCW);
shadowpath.op(path, shadowpath, Path.Op.INTERSECT);
}
return new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
if (path.isConvex()) {
outline.setConvexPath(shadowpath);
}
}
};
}
private static Path generateOutlinePolygonPath(
final List<RoundedRectangleShape> rectangles) {
final Path path = new Path();
for (final RoundedRectangleShape shape : rectangles) {
final Path rectanglePath = new Path();
rectanglePath.addRect(shape.mBoundingRectangle, Path.Direction.CW);
path.op(rectanglePath, Path.Op.UNION);
}
return path;
}
@Override
public Path getTouchableArea() {
Path path = new Path();
for (DrawElement element : elements) {
DrawElement temp = (DrawElement) element.clone();
temp.applyDisplayMatrixToData();
path.op(temp.getTouchableArea(), Path.Op.UNION);
}
return path;
}
/**
* 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);
}
}
@RequiresApi(VERSION_CODES.KITKAT)
private boolean pathOverlapsCorner(Path edgePath, int index) {
Path cornerPath = new Path();
cornerPaths[index].applyToPath(cornerTransforms[index], cornerPath);
RectF bounds = new RectF();
edgePath.computeBounds(bounds, /* exact = */ true);
cornerPath.computeBounds(bounds, /* exact = */ true);
edgePath.op(cornerPath, Op.INTERSECT);
edgePath.computeBounds(bounds, /* exact = */ true);
return !bounds.isEmpty() || (bounds.width() > 1 && bounds.height() > 1);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(getWidth()/2,getHeight()/2);
canvas.drawPoint(0,0,mPaint);
canvas.drawPoints(new float[]{getWidth()/2*0.8f,0,
-getWidth()/2*0.8f,0,
0,getHeight()/2*0.8f,
0,-getHeight()/2*0.8f},mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawLine(-getWidth()/2*0.8f,0,getWidth()/2*0.8f,0,mPaint);
canvas.drawLine(0,-getHeight()/2*0.8f,0,getHeight()/2*0.8f,mPaint);
mPaint.setColor(Color.BLACK);
//绘制X轴箭头
canvas.drawLines(new float[]{
getWidth()/2*0.8f,0,getWidth()/2*0.8f*0.95f,-getWidth()/2*0.8f*0.05f,
getWidth()/2*0.8f,0,getWidth()/2*0.8f*0.95f,getWidth()/2*0.8f*0.05f
},mPaint);
//绘制Y轴箭头
canvas.drawLines(new float[]{
0,getHeight()/2*0.8f,getWidth()/2*0.8f*0.05f,getHeight()/2*0.8f-getWidth()/2*0.8f*0.05f,
0,getHeight()/2*0.8f,-getWidth()/2*0.8f*0.05f,getHeight()/2*0.8f-getWidth()/2*0.8f*0.05f,
},mPaint);
Path path = new Path();
// Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.mipmap.single);
// Matrix matrix =new Matrix();
// System.out.println(bitmap.getWidth()+"//"+bitmap.getHeight());
// matrix.postScale(0.5f,0.5f);
// Bitmap b = bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
// path.addCircle(0,0,Math.min(bitmap.getWidth()/4,bitmap.getHeight()/4), Path.Direction.CW);
// canvas.clipPath(path, Region.Op.INTERSECT);
// canvas.drawBitmap(b,-bitmap.getWidth()/4,-bitmap.getHeight()/4,mPaint);
mPaint.setStyle(Paint.Style.FILL);
Path path1 = new Path();
Path path2 = new Path();
path1.moveTo(0,0);
path1.arcTo(new RectF(-200,-200,200,200),240,60,false);
path1.lineTo(0,0);
path2.moveTo(0,0);
path2.arcTo(new RectF(-300,-300,300,300),240,60,false);
path2.lineTo(0,0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path.op(path1,path2, Path.Op.XOR);
}
canvas.drawPath(path,mPaint);
}
private void appendEdgePath(@NonNull ShapeAppearancePathSpec spec, int index) {
int nextIndex = (index + 1) % 4;
scratch[0] = cornerPaths[index].getEndX();
scratch[1] = cornerPaths[index].getEndY();
cornerTransforms[index].mapPoints(scratch);
scratch2[0] = cornerPaths[nextIndex].getStartX();
scratch2[1] = cornerPaths[nextIndex].getStartY();
cornerTransforms[nextIndex].mapPoints(scratch2);
float edgeLength = (float) Math.hypot(scratch[0] - scratch2[0], scratch[1] - scratch2[1]);
// TODO(b/121352029): Remove this -.001f that is currently needed to handle rounding errors
edgeLength = Math.max(edgeLength - .001f, 0);
float center = getEdgeCenterForIndex(spec.bounds, index);
shapePath.reset(0, 0);
EdgeTreatment edgeTreatment = getEdgeTreatmentForIndex(index, spec.shapeAppearanceModel);
edgeTreatment.getEdgePath(edgeLength, center, spec.interpolation, shapePath);
Path edgePath = new Path();
shapePath.applyToPath(edgeTransforms[index], edgePath);
if (edgeIntersectionCheckEnabled
&& VERSION.SDK_INT >= VERSION_CODES.KITKAT
&& (edgeTreatment.forceIntersection()
|| pathOverlapsCorner(edgePath, index)
|| pathOverlapsCorner(edgePath, nextIndex))) {
// Calculate the difference between the edge and the bounds to calculate the part of the edge
// outside of the bounds of the shape.
edgePath.op(edgePath, boundsPath, Op.DIFFERENCE);
// Add a line to the path between the previous corner and this edge.
// TODO(b/144784590): handle the shadow as well.
scratch[0] = shapePath.getStartX();
scratch[1] = shapePath.getStartY();
edgeTransforms[index].mapPoints(scratch);
overlappedEdgePath.moveTo(scratch[0], scratch[1]);
// Add this to the overlappedEdgePath which will be unioned later.
shapePath.applyToPath(edgeTransforms[index], overlappedEdgePath);
} else {
shapePath.applyToPath(edgeTransforms[index], spec.path);
}
if (spec.pathListener != null) {
spec.pathListener.onEdgePathCreated(shapePath, edgeTransforms[index], index);
}
}
@TargetApi(19)
private static void intersect(Path path1, Path path2) {
path1.op(path2, Path.Op.INTERSECT);
}