【问题标题】:Overlay behavior when zooming缩放时的叠加行为
【发布时间】:2012-10-24 14:58:00
【问题描述】:

我在使用叠加层时遇到问题。我在地图上绘制了一个多边形叠加层,但是,当我放大或缩小时,边缘不再与我想要的位置对齐。我该如何解决这个问题?

这是我启动应用程序时的样子(它完美地覆盖了整个停车场): Correct

这是我缩小时的样子(边缘不再与停车场对齐。叠加层看起来比停车场大一点): Zoomed out

此外,当我放大时,它并没有很好地对齐。在这种情况下,叠加层比停车场要小一些。 (抱歉,stackoverflow 不允许我发布超过 2 个链接)

关于如何解决此问题的任何建议?

代码如下:

private Projection projection; 
private List<Overlay> mapOverlays;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    MapView mapView = (MapView) findViewById(R.id.mapView); 
    mapView.setBuiltInZoomControls(true);

    MapController mc = mapView.getController();
    mc.setZoom(17); 
    mc.animateTo(new GeoPoint((int)(32.734248*1E6), (int)(-97.113448*1E6)));

    mapOverlays = mapView.getOverlays();        
    projection = mapView.getProjection();
    mapOverlays.add(new MyOverlay());        

    mapView.postInvalidate();
}

@Override
protected boolean isRouteDisplayed() {
    return false;
}

class MyOverlay extends Overlay{

    public MyOverlay(){

    }   

    public void draw(Canvas canvas, MapView mapv, boolean shadow){
        super.draw(canvas, mapv, shadow);

        Paint   mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAlpha(100);

        GeoPoint gP1 = new GeoPoint(32733839,-97112976);
        GeoPoint gP2 = new GeoPoint(32733875, -97113448);
        GeoPoint gP3 = new GeoPoint(32734961,-97113455);
        GeoPoint gP4 = new GeoPoint(32734953, -97112962);

        Point p1 = new Point();
        Point p2 = new Point();
        Point p3 = new Point();
        Point p4 = new Point();
        Path path = new Path();

        projection.toPixels(gP1, p1);
        projection.toPixels(gP2, p2);
        projection.toPixels(gP3, p3);
        projection.toPixels(gP4, p4);

        path.moveTo(p1.x, p1.y);
        path.lineTo(p2.x,p2.y);
        path.lineTo(p3.x,p3.y);
        path.lineTo(p4.x,p4.y);

        canvas.drawPath(path, mPaint);
    }
}

}

【问题讨论】:

  • 您应该发布一些代码,因为您可能会遇到精度问题。
  • 您确定您的积分已转换correctly
  • 是的,它们是微度数。
  • 一切看起来都正确(抱歉-我错过了微度数)...最后一项我会验证是否以更高的缩放显式调用 view.invalidate/postInvalidate(非 UI 线程)有帮助...
  • 我不确定非 ui 线程是什么意思。我添加了 mapv.invalidate();在 canvas.drawPath 之后,在 draw 方法中。这是你的意思吗?这并不能解决问题。

标签: android google-maps android-mapview overlays


【解决方案1】:

每次缩放改变时,Projection 也会改变。即使您在地图中进行较大移动而不更改缩放比例,投影也可能会发生变化。

要更正您的代码,您需要添加如下行:

public void draw(Canvas canvas, MapView mapv, boolean shadow){ 
    super.draw(canvas, mapv, shadow); 

    Projection projection = mapv.getProjection();  //Add this line

    Paint   mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
    mPaint.setColor(Color.RED); 
    mPaint.setStyle(Paint.Style.FILL); 
    mPaint.setAlpha(100); 

    GeoPoint gP1 = new GeoPoint(32733839,-97112976); 
    GeoPoint gP2 = new GeoPoint(32733875, -97113448); 
    GeoPoint gP3 = new GeoPoint(32734961,-97113455); 
    GeoPoint gP4 = new GeoPoint(32734953, -97112962); 

    Point p1 = new Point(); 
    Point p2 = new Point(); 
    Point p3 = new Point(); 
    Point p4 = new Point(); 
    Path path = new Path(); 

    projection.toPixels(gP1, p1); 
    projection.toPixels(gP2, p2); 
    projection.toPixels(gP3, p3); 
    projection.toPixels(gP4, p4); 

    path.moveTo(p1.x, p1.y); 
    path.lineTo(p2.x,p2.y); 
    path.lineTo(p3.x,p3.y); 
    path.lineTo(p4.x,p4.y); 

    canvas.drawPath(path, mPaint); 
} 

您可以删除在onCreate() 中创建的投影。

--已编辑--

改进 - 速战速决

onDraw() 每次移动地图或更改缩放级别时都会被调用两次,因此尽可能做到这一点很重要。您可以在下面找到一些建议:

private List<Overlay> mapOverlays; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    MapView mapView = (MapView) findViewById(R.id.mapView);  
    mapView.setBuiltInZoomControls(true); 

    MapController mc = mapView.getController(); 
    mc.setZoom(17);  
    mc.animateTo(new GeoPoint((int)(32.734248*1E6), (int)(-97.113448*1E6))); 

    mapOverlays = mapView.getOverlays();         
    mapOverlays.add(new MyOverlay());         

    mapView.postInvalidate(); 
} 

@Override 
protected boolean isRouteDisplayed() { 
    return false; 
} 

class MyOverlay extends Overlay{ 

    //Moved objects that need only one instance to the initialization, to avoid creating a new copy of each every time draw() runs  
    private Paint   mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private GeoPoint gP1 = new GeoPoint(32733839,-97112976); 
    private GeoPoint gP2 = new GeoPoint(32733875, -97113448); 
    private GeoPoint gP3 = new GeoPoint(32734961,-97113455); 
    private GeoPoint gP4 = new GeoPoint(32734953, -97112962); 

    private Point p1 = new Point(); 
    private Point p2 = new Point(); 
    private Point p3 = new Point(); 
    private Point p4 = new Point(); 
    private Path path = new Path(); 

    public MyOverlay(){
        //mPaint settings done on class creation, to avoid repeating them on draw() call 
        mPaint.setColor(Color.RED); 
        mPaint.setStyle(Paint.Style.FILL); 
        mPaint.setAlpha(100); 
    }    

    public void draw(Canvas canvas, MapView mapv, boolean shadow){ 
        super.draw(canvas, mapv, shadow); 

        //draw is always called twice, one with shadow equal to true and one to false.
        //This can be used to draw the same image with shadow
        //But you are not using shadows, so you can immediately return half of the calls, and reduce the draw() effort by half
        if(shadow) return;

        Projection projection = mapv.getProjection();

        projection.toPixels(gP1, p1); 
        projection.toPixels(gP2, p2); 
        projection.toPixels(gP3, p3); 
        projection.toPixels(gP4, p4); 

        path.rewind();
        path.moveTo(p1.x,p1.y); 
        path.lineTo(p2.x,p2.y); 
        path.lineTo(p3.x,p3.y); 
        path.lineTo(p4.x,p4.y); 

        canvas.drawPath(path, mPaint); 
    } 
} 

改进 - 更复杂的改进

我在下面描述的改进对于您当前的叠加层来说太过分了。只有当你有非常大的路径要绘制时才有意义。

当您在不缩放地图的情况下移动地图时,使用上面的代码,路径将被重新创建并在不同的位置重新绘制以与地图对齐。但是您创建的路径与之前的路径大小、形状相同,只是位置不同。

您可以使用以下方法获得相同的结果:

path.offset(dx, dy);

其中dx, dy 是移动路径以使其与地图对齐所需的像素数。当然,您需要跟踪上次偏移路径时地图在哪里,这样您就可以将路径偏移到新的地图位置。

如果您有一条包含数千个点的路径,则偏移该路径将比重新绘制它快 100 倍。

您还需要跟踪缩放级别,因为您仍然需要在缩放更改时重新创建路径。您不能使用getCurrentZoomLevel() 来执行此操作,因为它与缩放动画不同步。您需要测试longitudeSpan() 值的变化,以便能够与缩放变化动画同步创建路径。

我希望这会有所帮助。

问候。

【讨论】:

  • 所以我添加了 Projection projection = mapv.getProjection();。 mapView 用于 onCreate() 中的 mapView。这对我不起作用。
  • 亲爱的@Kvothe,当有人花时间帮助我并指出我的代码中的错误时,我会说“感谢您的帮助,我已经更正了您指出的错误”,并且然后,如果我的代码仍然无法按预期工作,我会说“虽然,我的代码仍然有其他错误,因为现在有以下行为......你能帮我找到它们吗?”。我会等待对发现一个粗略错误的适当赞赏,然后再花时间查看您的代码,我相信您会发现,如果您不表示赞赏,没有多少人会花时间帮助您。跨度>
  • 对不起,我不是故意的(我责怪睡眠不足)。我的意思是我已经做出了你建议的改变,但没有奏效。它没有改变任何东西,并且应用程序的行为方式相同。我真的很感谢你和其他人在这个网站上提供的帮助,我真的不是故意不忘恩负义的。那么,请您接受我的道歉,并在有机会的时候再看看它吗?谢谢。
  • 不客气 :-)。我注意到您没有关闭路径,但这不应该是问题。我会仔细看看,我会回来找你的。
  • 在性能和内存利用率方面,你可以做几件事来改进你的代码(如果你愿意,我可以和你分享),但没有什么可以被认为是错误的。我已经测试了您的代码,并将其与使用 Internet Explorer 的谷歌地图的行为进行了比较。如果您打开此链接maps.google.pt/…(这是您的停车场)并更改缩放,您会看到标记会稍微上下移动。 (续)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
  • 2012-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多