Now below is my code that draws path between geopoints in map. This works perfectly fine. What I'm trying to implement is instead of drawing a line,display this path with the dots(.) as in iPhone. I want it to be like this gp1.........gp2 instead of drawing in a single straight line like gp1______gp2.
I have tried almost all the options for doing this but still no success on this, any one can help me solving this?
private void drawPath(List geoPoints, int color) {
List overlays = objMapView.getOverlays();
int loopcount = geoPoints.size() - 1;
for (int i = 0; i < loopcount; i++) {
GeoPoint p1 = (GeoPoint) geoPoints.get(i);
GeoPoint p2 = (GeoPoint) geoPoints.get(i + 1);
MyPathOverLay p = null;
/**** Marking the start and end of the trailpath ****/
if (i == 0) {
Bitmap bmp = BitmapFactory.decodeResource(this.getResources(),R.drawable.greenflag);
p = new MyPathOverLay(p1, p2, 0xFFFF0000, true, false, bmp);
} else if (i == loopcount - 1) {
Bitmap bmp = BitmapFactory.decodeResource(this.getResources(),R.drawable.redflag);
p = new MyPathOverLay(p1, p2, 0xFFFF0000, false, true, bmp);
} else {
p = new MyPathOverLay(p1, p2, 0xFFFF0000, false, false, null);
}
overlays.add(p);
}
}
public class MyPathOverLay extends Overlay {
private GeoPoint gp1;
private GeoPoint gp2;
private int color;
Boolean isFirstPOI;
Boolean isLastPOI;
AudioMap audioMap;
Bitmap bmp;
public MyPathOverLay(GeoPoint gp1, GeoPoint gp2, int color,Boolean first, Boolean last,Bitmap bitMap) {
this.gp1 = gp1;
this.gp2 = gp2;
this.color = color;
this.isFirstPOI= first;
this.isLastPOI = last;
this.bmp = bitMap;
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
Paint paint = new Paint();
Point point = new Point();
projection.toPixels(gp1, point);
paint.setColor(color);
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setStrokeWidth(5);
paint.setAlpha(120);
canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(gp1, screenPts);
//---translate the GeoPoint to screen pixels---
Point screenPts1 = new Point();
mapView.getProjection().toPixels(gp2, screenPts1);
if(isFirstPOI == true){
canvas.drawBitmap(bmp,screenPts.x-20,screenPts.y-40, null);
}
else if(isLastPOI == true) {
canvas.drawBitmap(bmp,screenPts1.x-20,screenPts1.y-35, null);
}
super.draw(canvas, mapView, shadow);
}
}
Thanks to this guy, I referred this example and it is working for me.
How do I make a dotted/dashed line in Android?
Just need to add these 2 lines,
paint.setPathEffect(new DashPathEffect(new float[] {10,10}, 5));
canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
after I set,
paint.setAlpha(120);
#Frankenstein, thank you
Related
I doing building a appplication direction from this point to that point on map google. My code run success, but when i zoom in map, draw line direction on map is lost. When zoom out map, my line draw appear. Can you help me!
this source code draw line between two point!
class MyOverLay extends Overlay {
private final List<GeoPoint> points;
private boolean drawStartEnd;
private int pathColor;
public MyOverLay(List<GeoPoint> pointToDraw) {
// TODO Auto-generated constructor stub
this(pointToDraw, Color.BLUE, true);
}
public MyOverLay(List<GeoPoint> points, int pathColor,
boolean drawStartEnd) {
this.points = points;
this.pathColor = pathColor;
this.drawStartEnd = drawStartEnd;
}
private void drawOval(Canvas canvas, Paint paint, Point point) {
Paint ovalPaint = new Paint(paint);
ovalPaint.setStyle(Paint.Style.FILL_AND_STROKE);
ovalPaint.setStrokeWidth(3);
ovalPaint.setColor(Color.BLUE);
int _radius = 7;
RectF oval = new RectF(point.x - _radius, point.y - _radius,
point.x + _radius, point.y + _radius);
canvas.drawOval(oval, ovalPaint);
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
Projection projection = mapView.getProjection();
if (shadow == false && points != null) {
Point startPoint = null, endPoint = null;
Path path = new Path();
// We are creating the path
for (int i = 0; i < points.size(); i++) {
GeoPoint gPointA = points.get(i);
Point pointA = new Point();
projection.toPixels(gPointA, pointA);
if (i == 0) { // This is the start point
startPoint = pointA;
path.moveTo(pointA.x, pointA.y);
} else {
if (i == points.size() - 1)// This is the end point
endPoint = pointA;
path.lineTo(pointA.x, pointA.y);
}
}
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(pathColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(8);
paint.setAlpha(100);
if (getDrawStartEnd()) {
if (startPoint != null) {
drawOval(canvas, paint, startPoint);
}
if (endPoint != null) {
drawOval(canvas, paint, endPoint);
}
}
if (!path.isEmpty())
canvas.drawPath(path, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
public boolean getDrawStartEnd() {
return drawStartEnd;
}
public void setDrawStartEnd(boolean markStartEnd) {
drawStartEnd = markStartEnd;
}
}
I have an app where an user is given a lot of points (100 or even more) and he has to physically go to those points and "check in". They have to go to those points in a certain order, so I need to display a route in the MapView which passes through all those points.
I've read a lot about getting the route between two points, but I can't find anything about drawing a complex route with a lot of points. Is this behavior possible?
public class RouteOverlay extends Overlay {
private GeoPoint gp1;
private GeoPoint gp2;
private int color;
public RouteOverlay(GeoPoint gp1, GeoPoint gp2, int color) {
this.gp1 = gp1;
this.gp2 = gp2;
this.color = color;
}
Now all that's left now for our Overlay is to override the draw() method and draw the line as we need it:
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
Paint paint = new Paint();
Point point = new Point();
projection.toPixels(gp1, point);
paint.setColor(color);
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setStrokeWidth(5);
paint.setAlpha(120);
canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
super.draw(canvas, mapView, shadow);
}
Back in the Activity, just iterate over the GeoPoints that you got from google maps and add each of them to the MapView:
private void drawPath(List geoPoints, int color) {
List overlays = mapView.getOverlays();
for (int i = 1; i < geoPoints.size(); i++) {
overlays.add(new RouteOverlay(geoPoints.get(i - 1), geoPoints.get(i), color));
}
}
Try something like this
if(DataSources.ActivitiesList.length >0)
{
String address = "http://maps.google.com/maps?daddr=" + DataSources.ActivitiesList[0].SiteLatitude.toString() + "," + DataSources.ActivitiesList[0].SiteLongitude.toString();
for (int i= 1 ;i < DataSources.ActivitiesList.length ; i++)
{
if(DataSources.ActivitiesList[i].SiteLatitude != null)
address += "+to:" + DataSources.ActivitiesList[i].SiteLatitude + "," + DataSources.ActivitiesList[i].SiteLongitude;
}
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(address));
startActivity(intent);
break;
}
My problem is that I want to create a method that when I invoke it giving it two GeoPoint's I want it to draw a line between the two points and I haven't been able to do this.
Thanks in advance.
public class MyOverlays extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mapOverlays = new ArrayList<OverlayItem>();
private Context context;
private int lastestIndex;
private Projection projection;
private Canvas canvas;
private MapView mapv;
private boolean shadow;
public MyOverlays(Context context, Drawable defaultMarker, String player) {
super(boundCenterBottom(defaultMarker));
this.context = context;
}
#Override
protected OverlayItem createItem(int i) {
return mapOverlays.get(i);
}
#Override
public int size() {
return mapOverlays.size();
}
public void setPj(Projection projection) {
this.projection = projection;
}
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, shadow);
this.canvas = canvas;
this.mapv = mapv;
this.shadow = shadow;
// Configuring the paint brush
}
Test method ideally i would want to pass 2 geopoints to draw a line between them
public void test() {
super.draw(canvas, mapv, shadow);
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
GeoPoint gP1 = new GeoPoint(34159000, 73220000);// starting point
GeoPoint gP2 = new GeoPoint(33695043, 73050000);// End point Islamabad
GeoPoint gP4 = new GeoPoint(33695043, 73050000);// Start point Islamabad
GeoPoint gP3 = new GeoPoint(33615043, 73050000);// End Point Rawalpindi
Point p1 = new Point();
Point p2 = new Point();
Path path1 = new Path();
Point p3 = new Point();
Point p4 = new Point();
Path path2 = new Path();
projection.toPixels(gP2, p3);
projection.toPixels(gP1, p4);
path1.moveTo(p4.x, p4.y);// Moving to Abbottabad location
path1.lineTo(p3.x, p3.y);// Path till Islamabad
projection.toPixels(gP3, p1);
projection.toPixels(gP4, p2);
path2.moveTo(p2.x, p2.y);// Moving to Islamabad location
path2.lineTo(p1.x, p1.y);// Path to Rawalpindi
canvas.drawPath(path1, mPaint);// Actually drawing the path from
// Abbottabad to Islamabad
canvas.drawPath(path2, mPaint);// Actually drawing the path from
// Islamabad to Rawalpindi
this.populate();
}
Resolved my issue,
public void draw(Canvas canvas, MapView mapv, boolean shadow){
super.draw(canvas, mapv, shadow);
this.canvas=canvas;
this.mapv=mapv;
this.shadow=shadow;
if(line==1){
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
GeoPoint gP1 = new GeoPoint(34159000,73220000);//starting point Abbottabad
GeoPoint gP2 = new GeoPoint(33695043,73050000);//End point Islamabad
GeoPoint gP4 = new GeoPoint(33695043, 73050000);//Start point Islamabad
GeoPoint gP3 = new GeoPoint(33615043, 73050000);//End Point Rawalpindi
Point p1 = new Point();
Point p2 = new Point();
Path path1 = new Path();
Point p3 = new Point();
Point p4 = new Point();
Path path2 = new Path();
projection.toPixels(gP2, p3);
projection.toPixels(gP1, p4);
path1.moveTo(p4.x, p4.y);//Moving to Abbottabad location
path1.lineTo(p3.x,p3.y);//Path till Islamabad
projection.toPixels(gP3, p1);
projection.toPixels(gP4, p2);
path2.moveTo(p2.x, p2.y);//Moving to Islamabad location
path2.lineTo(p1.x,p1.y);//Path to Rawalpindi
canvas.drawPath(path1, mPaint);//Actually drawing the path from Abbottabad to Islamabad
canvas.drawPath(path2, mPaint);//Actually drawing the path from Islamabad to Rawalpindi
}
//Configuring the paint brush
}
public void test(){
System.out.println("vim ao test");
line=1;
draw(canvas,mapv,shadow);
}
I need to draw shapes just like those you would create with custom maps on Google Maps, using Android's MapView.
In other words, if I draw a shape on the map, when I zoom out it should shrink, covering the same area of the map regardless of the zoom level.
Example following the Android Reference:
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(p, screenPts);
Paint boxPaint = new Paint();
boxPaint.setColor(android.graphics.Color.WHITE);
boxPaint.setStyle(Paint.Style.FILL);
boxPaint.setAlpha(140);
canvas.drawCircle(screenPts.x, screenPts.y, 20, boxPaint);
return true;
}
This shows a white circle on the map, but if you zoom out, the circle is the same size. Perhaps using canvas is not right approach?
I need something like how Google Maps highlights neighborhoods or cities:
Any ideas? Thanks in advance!
I had the same problem myself, here's a full solution with demo locations:
import java.util.*;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.graphics.Region.Op;
import android.os.Bundle;
import com.google.android.maps.*;
public class ShapeOverlayTest extends MapActivity {
private MapView m_map;
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_map = (MapView) findViewById(R.id.mapview);
m_map.displayZoomControls(true);
m_map.setBuiltInZoomControls(true);
}
#Override
protected void onStart() {
super.onStart();
Loc[][] areas = {
{
new Loc(51.51695436113811, -0.28686325139653757),
new Loc(51.5268179962453, -0.28118722558738923),
new Loc(51.526498459594215, -0.27779666308279755),
new Loc(51.52521530775356, -0.26943974607777654),
new Loc(51.52292555645698, -0.25813738590178786),
new Loc(51.52054465991048, -0.2498381618983569),
new Loc(51.51012230470141, -0.24509233633017083),
new Loc(51.50884762913046, -0.24465130560570497),
new Loc(51.50732063336974, -0.2441767643132881),
new Loc(51.50431624597833, -0.24473900326760137),
new Loc(51.49756328092904, -0.2714528238165076),
new Loc(51.50092541797557, -0.28360267232347336),
new Loc(51.50205958485736, -0.28490018935582045),
new Loc(51.50488447379555, -0.28681164237730944)
},
{
new Loc(51.50368617913765, -0.25313579464343156),
new Loc(51.51978611305675, -0.24842567405905958),
new Loc(51.51039382684418, -0.24460628015366626),
new Loc(51.508792552597576, -0.24397604687682156),
new Loc(51.50713008309719, -0.24346350415674722),
new Loc(51.502411013302684, -0.2508501075008919),
new Loc(51.502377240039664, -0.25160073203846817),
new Loc(51.50274364303565, -0.25204783703705536)
},
{
new Loc(51.49924084955314, -0.2858705706471945),
new Loc(51.50212820259818, -0.2791479893522646),
new Loc(51.49724510427319, -0.27427453152961206),
new Loc(51.49429724502515, -0.2799184038304611),
new Loc(51.494270969987404, -0.28180678948730314)
}
};
String[] areaNames = { "W3 Ealing", "W3 Hammersmith & Fulham", "W3 Hounslow" };
// for (Map.Entry<String, List<Loc>> area : m_areas.entrySet()) {
// // to have much less points and make sure they are in order
// // the demo data already has these properties
// // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm#Pseudocode
// area.setValue(Algo.convexHull(area.getValue()));
// }
Map<String, List<GeoPoint>> areaMap = new HashMap<String, List<GeoPoint>>();
for (int i = 0; i < areaNames.length; i++) {
List<GeoPoint> points = new ArrayList<GeoPoint>();
for (int j = 0; j < areas[i].length; j++) {
points.add(areas[i][j].toGeoPoint());
}
areaMap.put(areaNames[i], points);
}
m_map.getOverlays().add(new AreasOverlay(areaMap));
// TODO determine location better, e.g. averaging area points
GeoPoint center = new GeoPoint(51509704, -270710);
m_map.getController().setCenter(center);
m_map.getController().setZoom(15);
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
static class Loc {
private double m_lat;
private double m_lon;
public Loc(final double lat, final double lon) {
m_lat = lat;
m_lon = lon;
}
public GeoPoint toGeoPoint() {
return new GeoPoint((int) (m_lat * 1e6), (int) (m_lon * 1e6));
}
};
static class AreasOverlay extends Overlay {
private final Map<String, List<GeoPoint>> m_areas;
private final Paint m_paintFill;
private final Paint m_paintStroke;
private static final int ALPHA = 0x30ffffff; // 48 out of 255 transparent
private static final int[] COLORS =
{ Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.GREEN, Color.BLUE };
static {
for (int i = 0; i < AreasOverlay.COLORS.length; i++) {
AreasOverlay.COLORS[i] &= AreasOverlay.ALPHA;
}
}
public AreasOverlay(final Map<String, List<GeoPoint>> areaMap) {
m_areas = areaMap;
// prepare paints
m_paintFill = new Paint();
m_paintFill.setStyle(Paint.Style.FILL);
m_paintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
m_paintStroke.setStyle(Style.STROKE);
m_paintStroke.setAntiAlias(true);
m_paintStroke.setStrokeWidth(3);
}
#Override
public void draw(final Canvas canvas, final MapView mapView, final boolean shadow) {
super.draw(canvas, mapView, shadow);
if (shadow) {
return;
}
Projection projection = mapView.getProjection();
List<Path> areaPaths = getPaths(projection, m_areas);
drawPaths(canvas, areaPaths);
}
private List<Path> getPaths(final Projection projection, final Map<String, List<GeoPoint>> areas) {
List<Path> areaPaths = new ArrayList<Path>(areas.size());
for (Map.Entry<String, List<GeoPoint>> entry : areas.entrySet()) {
List<GeoPoint> sourceList = entry.getValue();
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
Iterator<GeoPoint> it = sourceList.iterator();
Point point = nextDrawPoint(projection, it);
path.moveTo(point.x, point.y);
while (it.hasNext()) {
point = nextDrawPoint(projection, it);
path.lineTo(point.x, point.y);
}
path.close();
areaPaths.add(path);
}
return areaPaths;
}
/**
* <ul>
* <li>Draw with different colors.
* <li>Draw strokes first for them to be always visible.
* <li>Draw fills next with each removing from the drawable area.
* </ul>
*/
private void drawPaths(final Canvas canvas, final List<Path> areaPaths) {
int currentColorIndex;
currentColorIndex = 0;
for (Path path : areaPaths) {
int currentColor = AreasOverlay.COLORS[currentColorIndex++];
currentColorIndex %= AreasOverlay.COLORS.length;
m_paintStroke.setColor(currentColor & 0xff7f7f7f); // make it darker by clearing the high bit
canvas.drawPath(path, m_paintStroke);
}
currentColorIndex = 0;
for (Path path : areaPaths) {
int currentColor = AreasOverlay.COLORS[currentColorIndex++];
currentColorIndex %= AreasOverlay.COLORS.length;
m_paintFill.setColor(currentColor);
canvas.drawPath(path, m_paintFill);
canvas.clipPath(path, Op.DIFFERENCE); // don't allow to draw over each other
}
}
private Point nextDrawPoint(final Projection projection, final Iterator<GeoPoint> it) {
GeoPoint geo = it.next();
Point p = new Point();
projection.toPixels(geo, p);
return p;
}
}
}
The radius for drawCircle is in pixels so it make sense that the circle is always the same size. You have to scale the radius based on the zoom level. The example below will graph a geometry from the JTS Topology Suite that will scale.
public class MapOverlay extends Overlay {
private static final String TAG = MapOverlay.class.getName();
// Allocate once and reuse
private final Paint mPaint = new Paint();
private final Path mPath = new Path();
// Region to highlight
private Geometry mGeometry;
/**
* #param geometry Region to highlight on map
*/
public MapOverlay(Geometry geometry) {
// Set region
mGeometry = geometry;
// Edit paint style
mPaint.setDither(true);
mPaint.setColor(Color.rgb(128, 136, 231));
mPaint.setAlpha(100);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
/**
* Draw the overlay over the map.
*
* #see com.google.android.maps.Overlay#draw(Canvas, MapView, boolean)
*/
#Override
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, shadow);
if (mGeometry != null) {
// TODO There could be more than one geometries
Geometry g = mGeometry.getGeometryN(0);
final Point p = new Point();
boolean first = true;
mPath.reset();
for (Coordinate c : g.getCoordinates()) {
// Convert lat/lon to pixels on screen
// GeoPoint is immutable so allocation is unavoidable
Projection projection = mapv.getProjection();
projection.toPixels(new GeoPoint((int) (c.y * 1E6), (int) (c.x * 1E6)), p);
// Set path starting point to first coordinate
// otherwise default start is (0,0)
if (first) {
mPath.moveTo(p.x, p.y);
first = false;
}
// Add new point to path
mPath.lineTo(p.x, p.y);
}
}
// Draw the path with give paint
canvas.drawPath(mPath, mPaint);
}
Adapted from here: MapSelectionOverlay.java
This maybe what you are looking for: Can "overlay" size be zoomed together with the google map on android?
public class ImpactOverlay extends Overlay {
private static int CIRCLERADIUS = 0;
private GeoPoint geopoint;
public ImpactOverlay(GeoPoint point, int myRadius) {
geopoint = point;
CIRCLERADIUS = myRadius;
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
// Transfrom geoposition to Point on canvas
Projection projection = mapView.getProjection();
Point point = new Point();
projection.toPixels(geopoint, point);
// the circle to mark the spot
Paint circle = new Paint();
circle.setColor(Color.BLACK);
int myCircleRadius = metersToRadius(CIRCLERADIUS, mapView, (double)geopoint.getLatitudeE6()/1000000);
canvas.drawCircle(point.x, point.y, myCircleRadius, circle);
}
public static int metersToRadius(float meters, MapView map, double latitude) {
return (int) (map.getProjection().metersToEquatorPixels(meters) * (1/ Math.cos(Math.toRadians(latitude))));
}
}
What you need is a list of lat/lon points for each shape you want to draw on the map. In the onDraw method, you need to iterate over that list (for each shape you want to draw), and do this:
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(p, screenPts);
then draw the shape on the canvas. IIRC that works correctly regardless of zoom, because the mapView is aware of the zoom level, and gives you the appropriate pixel location for the lat/long pair at that zoom level.
I am working on a project which is aboot drawing roads and displaying some informations about the roads. The issue is that I am using so many geopoints( 5.000-10.000 +) and drawing line points to points and showing the roads with different colors, so the map is too slow. I did some configurations about my application but still too slow.
Do you have any idea about solving my problem and being the performance better?
Here is the my code.
for (int t = 0; t < roads.size(); t++) {
for (int i = 0; i < roads.get(t).size() - 1; i++) {
//bounds up-bottom-right-left to draw roads
if (boundBox[0] >= roads.get(t).get(i)
.getLatitudeE6()
&& boundBox[1] >= roads.get(t).get(i)
.getLongitudeE6()
&& boundBox[2] <= roads.get(t).get(i)
.getLatitudeE6()
&& boundBox[3] <= roads.get(t).get(i)
.getLongitudeE6()) {
MyOverlay mOverlay = new MyOverlay();
mOverlay.setColor(Color.GREEN);
mOverlay.setWidth(4);
mOverlay.setPair(roads.get(t).get(i),
roads.get(t).get(i + 1));
mapOverlays.add(mOverlay);
}
}
}
class MyOverlay extends Overlay {
GeoPoint gp1 = new GeoPoint(0, 0);
GeoPoint gp2 = new GeoPoint(0, 0);
int colr=0,width=0;
public MyOverlay() {
}
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, false);
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(colr);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(width);
Point p1 = new Point();
Point p2 = new Point();
Path path = new Path();
Projection projection = mapv.getProjection();
projection.toPixels(gp1, p1);
projection.toPixels(gp2, p2);
path.moveTo((float) p2.x, (float) p2.y);
path.lineTo((float) p1.x, (float) p1.y);
// canvas.drawBitmap(markerBitmap, point.x, point.y, null);
canvas.drawPath(path, mPaint);
//canvas.drawBitmap(bitmap, src, dst, paint);
}
public void setPair(GeoPoint gpone, GeoPoint gptwo) {
gp1 = gpone;
gp2 = gptwo;
}
public void setColor(int clr)
{
colr=clr;
}
public void setWidth(int w)
{
width=w;
}
}
Is there anyone to solve my issue ?
There are a few things you can do to improve efficiency.
Your first block of code could be made slightly more efficient:
for (int t = 0, size = roads.size(); t < size; t++) { //Avoid calling '.size()' over and over
for (int i = 0; i < roads.get(t).size() - 1; i++) {//Avoid calling '.size()' over and over
final GeoPoint road = roads.get(t).get(i); //Reduce the number of get() calls.
if (boundBox[0] >= road.getLatitudeE6()
&& boundBox[1] >= road.getLongitudeE6()
&& boundBox[2] <= road.getLatitudeE6()
&& boundBox[3] <= road.getLongitudeE6()) {
MyOverlay mOverlay = new MyOverlay();
mOverlay.setColor(Color.GREEN);
mOverlay.setWidth(4);
mOverlay.setPair(road, roads.get(t).get(i + 1));
mapOverlays.add(mOverlay);
}
}
}
But most importantly, the biggest performance drain I can see in your code is that you are allocating a new rendering objects (Paint, Path, Point) every time draw() is called. This can be refactored so you reuse the same Paint instance:
class MyOverlay extends Overlay {
GeoPoint gp1 = new GeoPoint(0, 0);
GeoPoint gp2 = new GeoPoint(0, 0);
Point p1 = new Point();
Point p2 = new Point();
Path path = new Path();
int colr=0,width=0;
public MyOverlay() {
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(colr);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(width);
}
public void draw(Canvas canvas, MapView mapv, boolean shadow) {
super.draw(canvas, mapv, false);
path.reset();
Projection projection = mapv.getProjection();
projection.toPixels(gp1, p1);
projection.toPixels(gp2, p2);
path.moveTo((float) p2.x, (float) p2.y);
path.lineTo((float) p1.x, (float) p1.y);
canvas.drawPath(path, mPaint);
}
}
For more info see the 'Do's and Dont's section of the article here: http://android-developers.blogspot.com.au/2011/03/android-30-hardware-acceleration.html.
The relevant point from the article is: "Don't create render objects in draw methods: a common mistake is to create a new Paint, or a new Path, every time a rendering method is invoked. This is not only wasteful, forcing the system to run the GC more often, it also bypasses caches and optimizations in the hardware pipeline."