bill在【如何在Android中使用GoogleMap API】一文中介绍了在Android开发中使用GoogleMap API所需的准备工作,本文将在该准备工作就绪的前提下介绍如何在GoogleMap上显示自定义的地标。如下图所示:
其实Google Map中的地标(或者说图标更贴切)就是位于地图图层上的一个新图层,我们只需要简单的将自己的图标(或者是图标集合)添加到Google Map内置的图标图层里去即可。
以上文中的HelloGoogleMap为例
activity_main.xml
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <com.google.android.maps.MapView
- android:id="@+id/mapview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:apiKey="你所获得的API KEY"
- android:clickable="true" />
- </RelativeLayout>
- package com.billhoo.study.hellogooglemaps;
- import java.util.List;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import com.google.android.maps.GeoPoint;
- import com.google.android.maps.MapActivity;
- import com.google.android.maps.MapView;
- import com.google.android.maps.Overlay;
- import com.google.android.maps.OverlayItem;
- public class MainActivity extends MapActivity {
- MapView mMapView = null; //Google Map 对象
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mMapView = (MapView) findViewById(R.id.mapview);
- mMapView.setBuiltInZoomControls(true); // 使用�戎梅糯罂s小控制按钮
- @Override
- protected boolean isRouteDisplayed() {
- return false;
- }
- }
上述代码能够在MainActivity中显示GoogleMap,接下来我们将编写自定义的图标类HelloItemizedOverlay,本类维护一个图标集合,并在需要时由用户将本类对象添加进GoogleMap内置的图标集合中去,从而实现地图上图标的显示以及其他相关操作。代码如下:
- package com.billhoo.study.hellogooglemaps;
- import java.util.ArrayList;
- import android.app.AlertDialog;
- import android.content.Context;
- import android.graphics.drawable.Drawable;
- import com.google.android.maps.ItemizedOverlay;
- import com.google.android.maps.OverlayItem;
- @SuppressWarnings("rawtypes")
- public class HelloItemizedOverlay extends ItemizedOverlay {
- private ArrayList<OverlayItem> mOverlayItems = new ArrayList<OverlayItem>(); // 由本类维护的自定义图标集合和
- private Context mContext = null;
- public HelloItemizedOverlay(Drawable defaultMarker) {
- super(boundCenter(defaultMarker)); // 使用默认图标初始化父类
- }
- public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
- super(boundCenter(defaultMarker));
- mContext = context;
- }
- @Override
- protected OverlayItem createItem(int i) {
- return mOverlayItems.get(i);
- }
- @Override
- public int size() {
- return mOverlayItems.size();
- }
- /**
- * 当图标被点击时
- */
- @Override
- protected boolean onTap(int index) {
- OverlayItem item = mOverlayItems.get(index);
- AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
- dialog.setTitle(item.getTitle());
- dialog.setMessage(item.getSnippet());
- dialog.show();
- return true;
- }
- /**
- * 在本类维护的图标集合中添加一个新的图标
- *
- * @param overlay
- */
- public void addOverlay(OverlayItem overlay) {
- mOverlayItems.add(overlay);
- populate();
- }
- }
上述代码算是一个固定结构,期间重载了父类ItemizedOverlay的createItem(int i)、size()以及onTap(int index)方法,并且新增了一个用于添加新图标的addOverlay(OverlayItem overlay)方法(今后可以根据自己的需要增加诸如clear()、remove()等常用方法)。
接下来需要做的事情便是利用上述工具类进行图标的添加了,修改后的MainActivity如下:
- package com.billhoo.study.hellogooglemaps;
- import java.util.List;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import com.google.android.maps.GeoPoint;
- import com.google.android.maps.MapActivity;
- import com.google.android.maps.MapView;
- import com.google.android.maps.Overlay;
- import com.google.android.maps.OverlayItem;
- public class MainActivity extends MapActivity {
- private MapView mMapView = null; // Google Map 对象
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mMapView = (MapView) findViewById(R.id.mapview);
- mMapView.setBuiltInZoomControls(true); // 使用�戎梅糯罂s小控制按钮
- List<Overlay> mapOverlays = mMapView.getOverlays(); // 获取GoogleMap内置的图标集合
- Drawable drawable = this.getResources().getDrawable(
- R.drawable.cur_location);
- HelloItemizedOverlay itemizedOverlays = new HelloItemizedOverlay(
- drawable, this); // 使用cur_location这个图标初始化我们的工具类HelloItemizedOverlay
- GeoPoint point1 = new GeoPoint((int) (35.422006 * 1E6),
- (int) (104.084095 * 1E6)); // 构建一个GeoPoint位置对象,经度35.422006,纬度104.084095
- OverlayItem overlayItem1 = new OverlayItem(point1, "我的第一个地标", "随便找个点"); // 构建我们的第一个自定义图标,位于point1处
- GeoPoint point2 = new GeoPoint((int) (35.4 * 1E6), (int) (139.46 * 1E6)); // 同上
- OverlayItem overlayItem2 = new OverlayItem(point2, "这是第二个图标", "随便找的地点"); // 同上
- itemizedOverlays.addOverlay(overlayItem1); // 将我们的第一个图标添加进自定义图标集合
- itemizedOverlays.addOverlay(overlayItem2); // 将我们的第二个图标添加进该集合
- mapOverlays.add(itemizedOverlays); // 将我们的自定义图标集itemizedOverlays添加到GoogleMap内置的图标集合中去
- }
- @Override
- protected boolean isRouteDisplayed() {
- return false;
- }
- }
到此为止,在GoogleMap上显示自定义图标的基础部分已经全部完工,运行模拟器看看效果吧。
依次点击第一个以及第二个气泡,便会弹出我们之前设置好的提示信息
细心的朋友会发现,气泡的阴影部分怎么没有正确显示?别忙,请在代码段中加入如下处理
- ...
- OverlayItem overlayItem2 = new OverlayItem(point2, "这是第二个图标", "随便找的地点"); // 同上
- // 使图标阴影正确显示
- Drawable marker = this.getResources().getDrawable(
- R.drawable.cur_location);
- int w = marker.getIntrinsicWidth();
- int h = marker.getIntrinsicHeight();
- marker.setBounds(-w / 2, -h, w / 2, 0);
- overlayItem1.setMarker(marker); // 将overlayItem1的图标重新设置成marker
- // overlayItem2.setMarker(marker); //为了演示区别,第二个点不重新设置
- itemizedOverlays.addOverlay(overlayItem1); // 将我们的第一个图标添加进自定义图标集合
- ...
再次运行,发现第一个点的阴影已经正确显示了。
到此,bill已经将图标的添加介绍完毕,其中还包括了自己遇到的阴影错位问题的修正方法。但是,Android Google Map的陷阱还有很多,这也是bill这段时间以来一直在折腾的原因。接下来的文章,bill将一一向大家分享这些陷阱的解决方案,希望能够帮到那些像bill之前那样,对其中各种莫名其妙的异常或错误百思不得其解的朋友。