Reputation: 20934
I'm implementing custom path effect for route on top of MapView and I came up with the problem how to make my beginning and ending of the path rounded (like Paint.setStrokeCap(Cap.ROUND)
does). See screenshot - black lines - is my route I want to round at the end
Here is how I implemented my custom PathEffect:
public RouteOverlay(Context context)
{
mContext = context;
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(COLOR_DEFAULT);
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Cap.ROUND); // this one does not work...
mPaint.setStrokeJoin(Join.ROUND);
PathEffect e1 = new PathDashPathEffect(createRouteLineStyle(), 10, 3, PathDashPathEffect.Style.MORPH);
PathEffect e2 = new CornerPathEffect(10);
mPaint.setPathEffect(new ComposePathEffect(e1, e2));
}
private Path createRouteLineStyle()
{
Path p = new Path();
p.moveTo(-5, ROUTE_LINE_WIDTH/2);
p.lineTo(5,ROUTE_LINE_WIDTH/2);
p.lineTo(5,ROUTE_LINE_WIDTH/2-currentThickness);
p.lineTo(-5, ROUTE_LINE_WIDTH/2-currentThickness);
p.close();
p.moveTo(-5, -(ROUTE_LINE_WIDTH/2));
p.lineTo(5,-(ROUTE_LINE_WIDTH/2));
p.lineTo(5, -(ROUTE_LINE_WIDTH/2-currentThickness));
p.lineTo(-5, -(ROUTE_LINE_WIDTH/2-currentThickness));
return p;
}
@Override
public void draw(Canvas canvas, final MapView mapView, boolean shadow)
{
if(shadow) return;
if(mDrawEnabled)
{
synchronized(mPoints)
{
canvas.drawPath(mPath, mPaint);
}
}
}
As you can see on the screenshot, the ending of the line is not rounded (as well as beginning...). setStrokeCap(Cap.ROUND)
doesn't help.
So the question is - how to add round cap to my custom path? I was thinking of using addArc()
or addCircle()
to the end (and beginning) of my path, but this doesn't seem right.
The reason why I need custom path effect - is that I need to draw the route around actual road - so route should be empty inside and have inner and outer stroke lines.
In case somebody knows how to make this kind of path effect in some other way - please let me know, because this solution has big cons I have to deal with..
Upvotes: 1
Views: 5860
Reputation: 20934
I managed to find a solution for my problem. So I got rid of my custom path effect and started to use usual stroke (where stroke cap works as expected). So I basically draw my path 2 times: at first I draw black line, after that I draw thiner transparent line to clear the center of previous black line.
The only trick in this approach is that I need to draw my path in a separate bitmap (using temp canvas) and when path bitmap is ready - render it to the main canvas.
@Override
public void draw(Canvas canvas, final MapView mapView, boolean shadow)
{
//Generate new bitmap if old bitmap doesn't equal to the screen size (f.i. when screen orientation changes)
if(pathBitmap == null || pathBitmap.isRecycled() || pathBitmap.getWidth()!=canvas.getWidth() || pathBitmap.getHeight()!=canvas.getHeight())
{
if(pathBitmap != null)
{
pathBitmap.recycle();
}
pathBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888);
tempCanvas.setBitmap(pathBitmap);
}
//Render routes to the temporary bitmap
renderPathBitmap();
//Render temporary bitmap onto main canvas
canvas.drawBitmap(pathBitmap, 0, 0, null);
}
}
private void renderPath(Path path, Canvas canvas)
{
routePaint.setStrokeWidth(ROUTE_LINE_WIDTH);
routePaint.setColor(OUTER_COLOR);
routePaint.setXfermode(null);
canvas.drawPath(path, routePaint); //render outer line
routePaint.setStrokeWidth(ROUTE_LINE_WIDTH/1.7f);
routePaint.setColor(Color.TRANSPARENT);
routePaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
canvas.drawPath(path, routePaint); //render inner line
}
So result looks like:
Upvotes: 2
Reputation: 1198
I don't see any reason why that should not work unless you are running into the problem mentioned here http://code.google.com/p/android/issues/detail?id=24873.
Upvotes: 2