在 Android OverlayItem 中使用自定义 Drawable 绘制位置时出现问题
这段代码正在使用 Google API(级别 8)。
当我更新 OverlayItem 以使用自定义可绘制画布时 对象似乎在错误的位置绘制像素。在这个 例如我正在尝试在路易斯安那州画一个圆圈。当查看 整个地图上的圆圈是从地图上画出来的。当您放大“新建”时 在奥尔良,您会看到圆圈接近适当的纬度,并且 经度。热点似乎位于正确的位置,没有 不管圆画在哪里。
如果,在draw方法中,调用了canvas的恢复方法circle 绘制在正确的位置。
另外,如果不使用自定义可绘制对象,则图标将绘制在 正确的位置(不使用画布“恢复”)。
下面是显示此行为的代码。我尝试添加“setBounds” 和“boundCenterBottom”,因为其他人似乎表明 解决了“位置错误”的问题。尽管 老实说,我不确定为什么需要这些电话。
=======================================================================
public class MapsActivity extends MapActivity
{
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
// Itemized Overlay
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable defaultIcon =
this.getResources().getDrawable(R.drawable.icon);
MyItemizedOverlay itemizedoverlay = new
MyItemizedOverlay(defaultIcon, this);
// Overlay Item
GeoPoint pt = new GeoPoint(30000000, -90000000);
OverlayItem item = new OverlayItem(pt,"New Orleans",
"Louisiana");
// Custom Drawable
CustomDrawable customDrawable = new CustomDrawable(pt,
mapView);
boolean showProblem = true;
if (showProblem)
{
item.setMarker(customDrawable);
}
else
{
item.setMarker(defaultIcon);
}
// Add item we want to overlay
itemizedoverlay.addOverlay(item);
// Add overlay
mapOverlays.add(itemizedoverlay);
}
protected boolean isRouteDisplayed()
{
return false;
}
}
=======================================================================
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem>
{
private ArrayList<OverlayItem> mOverlays = new
ArrayList<OverlayItem>();
private Context mContext;
public MyItemizedOverlay(Drawable defaultMarker, Context context)
{
super(boundCenterBottom(defaultMarker));
mContext = context;
}
public void addOverlay(OverlayItem item)
{
mOverlays.add(item);
populate();
}
public void removeOverlay(OverlayItem item)
{
mOverlays.remove(item);
}
public void removeOverlay(int item)
{
mOverlays.remove(item);
}
protected OverlayItem createItem(int i)
{
OverlayItem item = mOverlays.get(i);
Drawable drawable = item.getMarker(0);
if (drawable != null)
{
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, w, h);
item.setMarker(boundCenterBottom(drawable));
}
return item;
}
public void draw(android.graphics.Canvas canvas, MapView mapView,
boolean shadow)
{
if (shadow)
return;
super.draw(canvas, mapView, shadow);
}
public int size()
{
return mOverlays.size();
}
protected boolean onTap(int index)
{
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new
AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
}
=======================================================================
public class CustomDrawable extends ShapeDrawable
{
private int radius = 10;
private GeoPoint point = null;
private MapView mapView = null;
public CustomDrawable(GeoPoint point, MapView mapView)
{
this.point = point;
this.mapView = mapView;
}
public void draw(Canvas canvas)
{
// TODO This (somewhat) fixes projection problem?
//canvas.restore();
Projection projection = mapView.getProjection();
Point pt = projection.toPixels(point, null);
canvas.drawCircle(pt.x, pt.y, radius,
getPaint());
}
public int getIntrinsicHeight()
{
return 2 * radius;
}
public int getIntrinsicWidth()
{
return 2 * radius;
}
}
=======================================================================
This code is using
the Google APIs (level 8).
When I update the OverlayItem to use a custom drawable the Canvas
object seems to draw the pixels in the wrong location. In this
example I'm trying to draw a circle in Louisiana. When viewing the
entire map the circle is drawn off the map. As you zoom into New
Orleans you'll see the circle approach the appropriate latitude and
longitude. The hot spot seems to be in the correct location, no
matter where the circle is being drawn.
If, in the draw method, the canvas restore method is called the circle
draws in the correct location.
Also If the custom drawable is not used, the icon is drawn in the
correct location (without using Canvas "restore").
Below is the code showing this behavior. I tried adding "setBounds"
and "boundCenterBottom", since other people seemed to indicate that
resolved their "wrong location" problems. Though
to be honest I'm not sure why those calls are needed.
=======================================================================
public class MapsActivity extends MapActivity
{
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
// Itemized Overlay
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable defaultIcon =
this.getResources().getDrawable(R.drawable.icon);
MyItemizedOverlay itemizedoverlay = new
MyItemizedOverlay(defaultIcon, this);
// Overlay Item
GeoPoint pt = new GeoPoint(30000000, -90000000);
OverlayItem item = new OverlayItem(pt,"New Orleans",
"Louisiana");
// Custom Drawable
CustomDrawable customDrawable = new CustomDrawable(pt,
mapView);
boolean showProblem = true;
if (showProblem)
{
item.setMarker(customDrawable);
}
else
{
item.setMarker(defaultIcon);
}
// Add item we want to overlay
itemizedoverlay.addOverlay(item);
// Add overlay
mapOverlays.add(itemizedoverlay);
}
protected boolean isRouteDisplayed()
{
return false;
}
}
=======================================================================
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem>
{
private ArrayList<OverlayItem> mOverlays = new
ArrayList<OverlayItem>();
private Context mContext;
public MyItemizedOverlay(Drawable defaultMarker, Context context)
{
super(boundCenterBottom(defaultMarker));
mContext = context;
}
public void addOverlay(OverlayItem item)
{
mOverlays.add(item);
populate();
}
public void removeOverlay(OverlayItem item)
{
mOverlays.remove(item);
}
public void removeOverlay(int item)
{
mOverlays.remove(item);
}
protected OverlayItem createItem(int i)
{
OverlayItem item = mOverlays.get(i);
Drawable drawable = item.getMarker(0);
if (drawable != null)
{
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, w, h);
item.setMarker(boundCenterBottom(drawable));
}
return item;
}
public void draw(android.graphics.Canvas canvas, MapView mapView,
boolean shadow)
{
if (shadow)
return;
super.draw(canvas, mapView, shadow);
}
public int size()
{
return mOverlays.size();
}
protected boolean onTap(int index)
{
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new
AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
}
=======================================================================
public class CustomDrawable extends ShapeDrawable
{
private int radius = 10;
private GeoPoint point = null;
private MapView mapView = null;
public CustomDrawable(GeoPoint point, MapView mapView)
{
this.point = point;
this.mapView = mapView;
}
public void draw(Canvas canvas)
{
// TODO This (somewhat) fixes projection problem?
//canvas.restore();
Projection projection = mapView.getProjection();
Point pt = projection.toPixels(point, null);
canvas.drawCircle(pt.x, pt.y, radius,
getPaint());
}
public int getIntrinsicHeight()
{
return 2 * radius;
}
public int getIntrinsicWidth()
{
return 2 * radius;
}
}
=======================================================================
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的
CustomDrawable
不应相对于地图定位自身。它应该只在其边界内绘制自身,而不引用MapView
或其Projection
。ItemizedOverlay
负责为您的OverlayItem
定位Drawable
。Your
CustomDrawable
shouldn't be positioning itself with respect to the map. It should just draw itself within its bounds, and not reference theMapView
or itsProjection
.ItemizedOverlay
takes care of positioning theDrawable
for yourOverlayItem
.