Android的api中没有直接提供气球和信息窗口的控件的实现,所以时常要开发带信息窗口的气球实现类,这时需要自定义一个气球overlay来继com.google.android.maps.Overlay
类,overlay就是可以自定义绘制的覆盖在地图上面的一个层。下面是代码:
1. package morgen.mstx;
2.
3. import java.util.ArrayList;
4. import java.util.List;
5. import android.view.MotionEvent;
6. import com.google.android.maps.GeoPoint;
7. import com.google.android.maps.MapView;
8. import com.google.android.maps.Overlay;
9. import com.google.android.maps.Projection;
10. import android.graphics.*;
11.
12. class MyBallonOverlay extends Overlay{
13. final static int picWidth=20; //气球图的宽度
14. final static int picHeight=34; //气球图的高度
15. final static int arcR=8;//信息窗口的圆角半径
16.
17. static MyBallonOverlay currentBallon=null;//表示当前选中的气球
18. String msg;
19.
20. boolean showWindow=false;
21.
22. //此气球对应的经纬度
23.
24. public MyBallonOverlay(GeoPoint gp,String msg){
25. this.gp=gp;
26. this.msg=msg;
27. }
28.
29. public GeoPoint getGeoPoint(){//获得该气球的经纬度GeoPoint
30. return gp;
31. }
32.
33. @Override
34. public boolean onTouchEvent(MotionEvent event, MapView mv) {
35. if(currentBallon!=null&¤tBallon!=this){
36. //若当前气球不为空且不是自己,什么都不做
37. return false;
38. }
39. if(event.getAction() == MotionEvent.ACTION_DOWN){
40. //若在气球上按下则设置当前气球为自己,且当前状态为在气球上
41. int x=(int)event.getX();
42. int y=(int)event.getY();
43. Point p= getPoint(mv);
44.
45. int xb=p.x-picWidth/2;
46. int yb=p.y-picHeight;
47.
48. if(x>=xb&&x<xb+picWidth&&y>=yb&&y<yb+picHeight){
49. //若在自己这个气球上按下则设置自己为当前气球
50. this;
51. return true;
52. }
53. }
54. else if (event.getAction() == MotionEvent.ACTION_MOVE) {
55. //移动事件返回当前气球状态 若当前在气球上则返回true 屏蔽其他移动事件
56. return currentBallon!=null;
57. }
58. else if (event.getAction() == MotionEvent.ACTION_UP) {
59. //获取触控笔位置
60. int x=(int)event.getX();
61. int y=(int)event.getY();
62.
63. //获取气球在屏幕上的坐标范围
64. Point p= getPoint(mv);
65. int xb=p.x-picWidth/2;
66. int yb=p.y-picHeight;
67.
68. if(currentBallon==this&&x>=xb&&x<xb+picWidth&&y>=yb&&y<yb+picHeight){
69. //若当前气球为自己且在当前气球上抬起触控则显示当前气球内容
70. //显示完内容后清空当前气球
71. null;
72. showWindow=!showWindow;
73.
74. List<Overlay> overlays = mv.getOverlays();
75. this);//删除此气球再添加
76. this);//此气球就位于最上面了
77. for(Overlay ol:overlays){//清除其他气球的showWindow标记
78. if(ol instanceof MyBallonOverlay){
79. if(ol!=this){
80. false;
81. }
82. }
83. }
84. return true;
85. }
86. else if(currentBallon==this){
87. //若当前气球为自己但抬起触控不再自己上则清空气球状态并返回true
88. null;
89. return true;
90. }
91. }
92. return false;
93. }
94. @Override
95. public void draw(Canvas canvas, MapView mapView, boolean shadow) {
96. //将经纬度翻译成屏幕上的XY坐标
97. Point p= getPoint(mapView);
98. //在坐标指定位置绘制气球
99. 2, p.y-picHeight, null);
100.
101. if(showWindow){//如果showWindow为true则显示信息窗口
102. 160);
103. }
104. //调用父类绘制
105. super.draw(canvas, mapView, shadow);
106. }
107.
108. public Point getPoint(MapView mapView){//将经纬度翻译成屏幕上的XY坐标
109. Projection projettion = mapView.getProjection();
110. new Point();
111. projettion.toPixels(gp, p);
112. return p;
113. }
114.
115. public void drawWindow(Canvas canvas,Point p,int winWidth){//绘制信息窗口的方法
116. int charSize=15;
117. int textSize=16;
118. int leftRightPadding=2;
119.
120. //为信息分行
121. int lineWidth=winWidth-leftRightPadding*2;//每行的宽度
122. int lineCharCount=lineWidth/(charSize); //每行字符数
123. //扫描整个信息字符串分行
124. new ArrayList<String>();
125. "";
126. for(int i=0;i<msg.length();i++){
127. char c=msg.charAt(i);
128. if(c!='\n'){
129. currentRow=currentRow+c;
130. }
131. else{
132. if(currentRow.length()>0){
133. alRows.add(currentRow);
134. }
135. "";
136. }
137. if(currentRow.length()==lineCharCount){
138. alRows.add(currentRow);
139. "";
140. }
141. }
142. if(currentRow.length()>0){
143. alRows.add(currentRow);
144. }
145. int lineCount=alRows.size();//总行数
146. int winHeight=lineCount*(charSize)+2*arcR;//窗体高度
147. //创建paint对象
148. new Paint();
149. true);
150. paint.setTextSize(textSize);
151. //绘制 信息窗体圆角矩形
152. 255, 255,251,239);
153. int x1=p.x-winWidth/2;
154. int y1=p.y-picHeight-winHeight-1;
155. int x2=x1+winWidth;
156. int y2=y1+winHeight;
157. new RectF(x1,y1,x2,y2);
158. canvas.drawRoundRect(r, arcR, arcR, paint);
159. 255,198,195,198);
160. paint.setStyle(Paint.Style.STROKE);
161. 2);
162. canvas.drawRoundRect(r, arcR, arcR, paint);
163.
164. //循环绘制每行文字
165. 0);
166. 255, 10, 10, 10);
167. int lineY=y1+arcR+charSize;
168. for(String lineStr:alRows){
169. System.out.println("lineStr"+lineStr);
170. for(int j=0;j<lineStr.length();j++){
171. "";
172. canvas.drawText(colChar, x1+leftRightPadding+j*charSize, lineY, paint);
173. }
174. lineY=lineY+charSize;
175. }
176. }
177. }
上述的draw方法完成了在指定的未知绘制气球图片,并根据气球信息窗口的标志值来决定是否调用drawWindow方法来绘制气球对应的信息窗口。这个自定义的气球可以服务于
大部分涉及到谷歌地图的应用,我有很多应用的涉及到了这些代码,很是实用