12.1.2 Geopoint与MapView
在开始Google Map之前,先来认识下maps包下两个重要的类Geopoint 和MapView 。
Geopoint类是一个不可变类,表示一组经度和纬度值,以微度的整数形式存储。
public 构造方法GeoPoint(int latitudeE6, int longitudeE6)。
用给定的经度和纬度构造一个GeoPoint,单位微度(度* 1E6).
参数:
latitudeE6 - 该点的纬度,为保持Mercator投影精确度,其取值范围是[-80,80]。
longitudeE6 - 该点的经度,可被规范化到(-180, 180)。
public int getLatitudeE6()
返回GeoPoint对象的纬度,单位微度(度* 1E6).
返回值:
纬度.
public int getLongitudeE6()
返回GeoPoint对象的经度,单位微度(度* 1E6)。
返回值:
经度.
一个MapView显示一个由谷歌地图服务获得的数据地图。 当MapView具有焦点时,它将捕捉按键和触摸手势平移和自动缩放地图,包括处理瓷砖更多的地图网络请求。 它还提供了必要的UI元素,为用户控制地图上的所有。 您的应用程序也可以使用MapView类的方法来控制MapView编程和绘制在地图上的覆盖类型。
一般来说,MapView类提供对谷歌地图API的封装,让您的应用程序处理通过类方法谷歌地图数据,它可以让你的地图数据的工作,你将其他类型的意见。
MapView一个查看其中显示的地图(从谷歌地图服务获得的数据)。将捕捉按键和触摸手势平移和缩放地图。 它也可以通过编程方式控制( getController()可以得出一个数Overlay (在上面的地图的getOverlays()
该地图可以显示在一个模式的数量,见setSatellite(boolean) , setTraffic(boolean) ,和setStreetView(boolean) 。 它可以选择性地显示一个“十字线”的时候不是触摸模式,以帮助在使用泛到选择;看到setReticleDrawMode(com.google.android.maps.MapView.ReticleDrawMode) 它也描绘了在左下角的谷歌徽标。
首选变焦机制是内置变焦,见setBuiltInZoomControls(boolean) 。 当用户锅地图,缩放控制会自动在MapView底部所示。
该MapView也是ViewGroup的,让您与附加意见,或者到一个特定的像素偏移,或一个特定的纬度/经度对LayoutParameters。
一个MapView只能建造(或充气)由MapActivity 。 这是因为它依赖于后台线程在网络中进行访问和文件系统中,这些线程必须在牧养的生命周期管理的MapActivity 。 砖是缓存在您的应用程序的目录的文件系统。 高速缓存是自动管理的,这样你就不需要用它做什么,随时可以删除它。
12.1.3 Google Maps实战:漂亮的气泡地图
在地图应用中,我们经常会有对某景点进行查询,显示某景点详细信息的应用需求,这时候如果能在地图上,用手轻轻一按就快速查询,该有多好。接下来,一起来实现这一效果,带气泡的地图。效果如图12-5、图12-6和如图12-7所示。
第一步,先在layout目录下建立一个MapView ,附上申请的Google Maps API Key。
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout
3. xmlns:android="http://schemas.android.com/apk/res/android"
4. android:orientation="vertical"
5. android:layout_width="fill_parent"
6. android:layout_height="fill_parent">
7. <com.google.android.maps.MapView
8. xmlns:android="http://schemas.android.com/apk/res/android"
9. android:id="@+id/map_view"
10. android:layout_width="fill_parent"
11. android:layout_height="fill_parent"
12. android:clickable="true"
13. android:enabled="true"
14. android:apiKey="0jFDHBPUJ8bRtUCMX-R9jSPzRj2Gz1Kh879BonA"/>
15. </RelativeLayout>
第二步,创建一个用来显示气泡的布局 View
。
1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2. android:background="@drawable/pop"
3. android:layout_width="wrap_content"
4. android:layout_height="wrap_content"
5. android:paddingLeft="5px"
6. android:paddingTop="5px"
7. android:paddingRight="5px"
8. android:paddingBottom="20px"
9. >
10. <TextView android:id="@+id/map_bubbleTitle"
11. android:ellipsize="marquee"
12. android:layout_width="120px"
13. android:layout_height="wrap_content"
14. android:gravity="center_horizontal"
15. android:textColor="#000000"
16. android:textSize="16dip"
17. android:singleLine="true"/>
18. <ImageView android:id="@+id/map_bubbleImage"
19. android:background="@drawable/narrow_select"
20. android:layout_width="30px"
21. android:layout_toRightOf="@id/map_bubbleTitle"
22. android:layout_height="wrap_content"/>
23.
24. <TextView android:id="@+id/map_bubbleText"
25. android:layout_width="150px"
26. android:layout_below="@id/map_bubbleTitle"
27. android:layout_height="wrap_content"
28. android:singleLine="false"/>
29. </RelativeLayout>
第三步,自定义一个 ItemizedOverlay
用来标识景点的图标和文字的图层。主要对该图层进行重新绘制,来达到想要的效果。
1. public class MyItemizedOverlay extends
2. private ArrayList<OverlayItem> overlayItemList = new
3. private
4. public
5. super(defaultMarker);
6. this.context=context;
7.
8. }
9.
10. @Override
11. public void draw(Canvas canvas, MapView mapView, boolean
12. super.draw(canvas, mapView, shadow);
13. // Projection接口用于屏幕像素点坐标系统和地球表面经纬度点坐标系统之间的变换
14. Projection projection = mapView.getProjection();
15. // 遍历所有的OverlayItem
16. for (int index = this.size() - 1; index >= 0; index--) {
17. // 得到给定索引的item
18. OverlayItem overLayItem = getItem(index);
19.
20. // 把经纬度变换到相对于MapView左上角的屏幕像素坐标
21. null);
22.
23. new
24. paintText.setColor(Color.RED);
25. 13);
26. // 绘制文本
27. 10, point.y - 15, paintText);
28. }
29.
30. }
31.
32. @Override
33. protected boolean onTap(int
34. // TODO Auto-generated method stub
35. setFocus(overlayItemList.get(index));
36. return super.onTap(index);
37. }
38.
39. @Override
40. protected OverlayItem createItem(int
41. return
42. }
43.
44. @Override
45. public int
46. return
47. }
48.
49. public void
50. overlayItemList.add(overlayItem);
51. this.populate();
52. }
53.
54. }
第四步,实现自己的 PopMapActivity
,先在地图上根据两景点经纬度创建位置,并以自定义的图标和文字进行标识,给自定义的
ItemizedOverlay
添加焦点改变事件监听,来完成气泡
View
的显示和隐藏效果。
1. public class PopMapActivity extends
2. /**
3. * 地图View
4. */
5. protected
6. /**
7. * 弹出的气泡View
8. */
9. private
10.
11. public void
12. super.onCreate(savedInstanceState);
13.
14. // 初始化气泡,并设置为不可见
15. this, R.layout.popview, null);
16. setContentView(R.layout.mymapview);
17. mapView = (MapView) findViewById(R.id.map_view);
18. new
19. MapView.LayoutParams.WRAP_CONTENT,
20. null,
21. MapView.LayoutParams.BOTTOM_CENTER));
22. // 由于气泡的尾巴是在下边居中的,因此要设置成
23. MapView.LayoutParams.BOTTOM_CENTER.
24. // 这里没有给GeoPoint,在onFocusChangeListener中设置
25. popView.setVisibility(View.GONE);
26. /**
27. * 创建图标资源(用于显示在overlayItem所标记的位置)
28. */
29. this.getResources().getDrawable(
30. R.drawable.mis_usemobile);
31. // 为maker定义位置和边界
32. 0, 0, drawable.getIntrinsicWidth(),
33. drawable.getIntrinsicHeight());
34. new MyItemizedOverlay(this, drawable);
35. // 设置显示/隐藏气泡的监听器
36. overlay.setOnFocusChangeListener(onFocusChangeListener);
37. /**
38. * 创建并添加第一个标记:深圳 世界之窗(经度:22.5348 纬度:113.97246)
39. */
40. // 构造一个经纬度点
41. new GeoPoint((int) (22.5348
42. int) (113.97246
43. // 创建标记(世界之窗)
44. new OverlayItem(point, "世界之窗",
45. "位于中国广东省深圳市南山区华侨城的大型文化旅游景区,是深圳最为著名的旅游景点之一。");
46. // 将标记添加到图层中(可添加多个OverlayItem)
47. overlay.addOverlay(overlayItem);
48.
49. /**
50. * 创建并添加第二个标记:锦绣中华(经度:22.53108 纬度:113.99151)
51. */
52. new GeoPoint((int) (22.53108 * 1E6), (int) (113.99151
53. // 创建标记(锦绣中华)
54. new OverlayItem(point, "锦绣中华",
55. "中国旅游胜地四十佳之一,是目前世界上最大的实景微缩景区,已入选中国世界纪录协会世界最大实景微缩景区候选世界纪录。 ");
56. // 将标记添加到图层中(可添加多个OverlayItem)
57. overlay.addOverlay(overlayItem);
58.
59. /**
60. * 往地图上添加自定义的ItemizedOverlay
61. */
62. List<Overlay> mapOverlays = mapView.getOverlays();
63. mapOverlays.add(overlay);
64.
65. // 设置地图模式为交通地图
66. true);
67. // 设置启用内置的缩放控件
68. true);
69. /**
70. * 取得地图控制器对象,用于控制MapView
71. */
72. // 设置地图的中心
73. mapView.getController().setCenter(point);
74. // 设置地图默认的缩放级别
75. 13);
76.
77. }
78.
79. @Override
80. protected boolean
81. // TODO Auto-generated method stub
82. return false;
83. }
84.
85. /**
86. * 监听器 当一个Overlay焦点改变时触发
87. */
88. private final ItemizedOverlay.OnFocusChangeListener onFocusChangeListener = new
89.
90. @Override
91. public void
92. {
93. // 创建气泡窗口
94. if (popView != null) {
95. popView.setVisibility(View.GONE);
96. }
97. if (newFocus != null) {
98.
99. MapView.LayoutParams geoLP = (MapView.LayoutParams) popView
100. .getLayoutParams();
101. // 这行用于popView的定位
102. TextView title = (TextView) popView
103. .findViewById(R.id.map_bubbleTitle);
104. title.setText(newFocus.getTitle());
105.
106. TextView desc = (TextView) popView
107. .findViewById(R.id.map_bubbleText);
108. if (newFocus.getSnippet() == null
109. 0) {
110. desc.setVisibility(View.GONE);
111. else
112. desc.setVisibility(View.VISIBLE);
113. desc.setText(newFocus.getSnippet());
114. }
115. mapView.updateViewLayout(popView, geoLP);
116. popView.setVisibility(View.VISIBLE);
117. }
118. }
119. };
120.
121. }
(以上是关于android应用开发全程实录中google map的部分章节,可以看到书的编写方式)