Android自定义气球Overlay的开发

android的api中没有直接提供气球和信息窗口的控件的实现,所以时常要开发带信息窗口的气球实现类,这时需要自定义一个气球overlay来继com.google.android.maps.Overlay

类,overlay就是可以自定义绘制的覆盖在地图上面的一个层。下面是代码:

001 package morgen.mstx;
002  
003 import java.util.ArrayList;
004 import java.util.List;
005 import android.view.MotionEvent;
006 import com.google.android.maps.GeoPoint;
007 import com.google.android.maps.MapView;
008 import com.google.android.maps.Overlay;
009 import com.google.android.maps.Projection;
010 import android.graphics.*;
011  
012 class MyBallonOverlay extends Overlay{
013     final static int picWidth=20;  //气球图的宽度
014     final static int picHeight=34//气球图的高度
015     final static int arcR=8;//信息窗口的圆角半径
016      
017     static MyBallonOverlay currentBallon=null;//表示当前选中的气球
018     String msg;   
019      
020     boolean showWindow=false;
021      
022     GeoPoint gp;//此气球对应的经纬度
023     
024     public MyBallonOverlay(GeoPoint gp,String msg){
025         this.gp=gp;
026         this.msg=msg;
027     }
028      
029     public GeoPoint getGeoPoint(){//获得该气球的经纬度GeoPoint
030         return gp;
031     }
032      
033     @Override
034     public boolean onTouchEvent(MotionEvent event, MapView mv) {
035         if(currentBallon!=null&¤tBallon!=this){
036             //若当前气球不为空且不是自己,什么都不做
037             return false;
038         }
039         if(event.getAction() == MotionEvent.ACTION_DOWN){
040             //若在气球上按下则设置当前气球为自己,且当前状态为在气球上         
041             int x=(int)event.getX();
042             int y=(int)event.getY();
043             Point p= getPoint(mv);
044              
045             int xb=p.x-picWidth/2;
046             int yb=p.y-picHeight;
047              
048             if(x>=xb&&x<xb+picWidth&&y>=yb&&y<yb+picHeight){
049                 //若在自己这个气球上按下则设置自己为当前气球               
050                 currentBallon=this;
051                 return true;
052             }
053         }
054         else if (event.getAction() == MotionEvent.ACTION_MOVE) {
055             //移动事件返回当前气球状态 若当前在气球上则返回true 屏蔽其他移动事件
056             return currentBallon!=null;
057         }           
058         else if (event.getAction() == MotionEvent.ACTION_UP) {
059             //获取触控笔位置
060             int x=(int)event.getX();
061             int y=(int)event.getY();
062              
063             //获取气球在屏幕上的坐标范围
064             Point p= getPoint(mv);            
065             int xb=p.x-picWidth/2;
066             int yb=p.y-picHeight;          
067              
068             if(currentBallon==this&&x>=xb&&x<xb+picWidth&&y>=yb&&y<yb+picHeight){
069                 //若当前气球为自己且在当前气球上抬起触控则显示当前气球内容   
070                 //显示完内容后清空当前气球
071                 currentBallon=null;    
072                 showWindow=!showWindow;
073                  
074                 List<Overlay> overlays = mv.getOverlays();
075                 overlays.remove(this);//删除此气球再添加
076                 overlays.add(this);//此气球就位于最上面了
077                 for(Overlay ol:overlays){//清除其他气球的showWindow标记
078                     if(ol instanceof MyBallonOverlay){
079                         if(ol!=this){
080                             ((MyBallonOverlay)ol).showWindow=false;
081                         }                        
082                     }
083                 }
084                 return true;
085             }
086             else if(currentBallon==this){
087                 //若当前气球为自己但抬起触控不再自己上则清空气球状态并返回true
088                 currentBallon=null;
089                 return true;               
090             }           
091         }
092         return false;
093     }
094     @Override
095     public void draw(Canvas canvas, MapView mapView, boolean shadow) {           
096         //将经纬度翻译成屏幕上的XY坐标
097         Point p= getPoint(mapView);             
098         //在坐标指定位置绘制气球
099         canvas.drawBitmap(MainActivity.bitmap, p.x-picWidth/2, p.y-picHeight, null);
100          
101         if(showWindow){//如果showWindow为true则显示信息窗口
102             drawWindow(canvas,p,160);
103         }
104         //调用父类绘制
105         super.draw(canvas, mapView, shadow);
106     }
107      
108     public Point getPoint(MapView mapView){//将经纬度翻译成屏幕上的XY坐标
109         Projection projettion = mapView.getProjection();
110         Point p = 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         ArrayList<String> alRows=new ArrayList<String>();
125         String currentRow="";
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                 currentRow="";
136             }
137             if(currentRow.length()==lineCharCount){
138                 alRows.add(currentRow);
139                 currentRow="";
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         Paint paint=new Paint();
149         paint.setAntiAlias(true);
150         paint.setTextSize(textSize);   
151         //绘制 信息窗体圆角矩形
152         paint.setARGB(255255,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         RectF r=new RectF(x1,y1,x2,y2);       
158         canvas.drawRoundRect(r, arcR, arcR, paint);
159         paint.setARGB(255,198,195,198);
160         paint.setStyle(Paint.Style.STROKE);
161         paint.setStrokeWidth(2);
162         canvas.drawRoundRect(r, arcR, arcR, paint);
163          
164         //循环绘制每行文字
165         paint.setStrokeWidth(0);
166         paint.setARGB(255101010);       
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                 String colChar=lineStr.charAt(j)+"";
172                 canvas.drawText(colChar, x1+leftRightPadding+j*charSize, lineY, paint);
173             }
174             lineY=lineY+charSize;
175         }
176     }
177 }

上述的draw方法完成了在指定的未知绘制气球图片,并根据气球信息窗口的标志值来决定是否调用drawWindow方法来绘制气球对应的信息窗口。这个自定义的气球可以服务于

大部分涉及到谷歌地图的应用,我有很多应用的涉及到了这些代码,很是实用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值