自定义开发气球com.google.android.maps.Overlay

jopen 12年前

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

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

package morgen.mstx;    import java.util.ArrayList;  import java.util.List;  import android.view.MotionEvent;  import com.google.android.maps.GeoPoint;  import com.google.android.maps.MapView;  import com.google.android.maps.Overlay;  import com.google.android.maps.Projection;  import android.graphics.*;    class MyBallonOverlay extends Overlay{      final static int picWidth=20;  //气球图的宽度      final static int picHeight=34; //气球图的高度      final static int arcR=8;//信息窗口的圆角半径            static MyBallonOverlay currentBallon=null;//表示当前选中的气球      String msg;                boolean showWindow=false;            GeoPoint gp;//此气球对应的经纬度           public MyBallonOverlay(GeoPoint gp,String msg){          this.gp=gp;          this.msg=msg;      }            public GeoPoint getGeoPoint(){//获得该气球的经纬度GeoPoint          return gp;      }            @Override      public boolean onTouchEvent(MotionEvent event, MapView mv) {          if(currentBallon!=null&¤tBallon!=this){              //若当前气球不为空且不是自己,什么都不做              return false;          }          if(event.getAction() == MotionEvent.ACTION_DOWN){              //若在气球上按下则设置当前气球为自己,且当前状态为在气球上                        int x=(int)event.getX();              int y=(int)event.getY();              Point p= getPoint(mv);                            int xb=p.x-picWidth/2;              int yb=p.y-picHeight;                            if(x>=xb&&x<xb+picWidth&&y>=yb&&y<yb+picHeight){                  //若在自己这个气球上按下则设置自己为当前气球                                  currentBallon=this;                  return true;              }          }          else if (event.getAction() == MotionEvent.ACTION_MOVE) {              //移动事件返回当前气球状态 若当前在气球上则返回true 屏蔽其他移动事件              return currentBallon!=null;          }                      else if (event.getAction() == MotionEvent.ACTION_UP) {              //获取触控笔位置              int x=(int)event.getX();              int y=(int)event.getY();                            //获取气球在屏幕上的坐标范围              Point p= getPoint(mv);                           int xb=p.x-picWidth/2;              int yb=p.y-picHeight;                                       if(currentBallon==this&&x>=xb&&x<xb+picWidth&&y>=yb&&y<yb+picHeight){                  //若当前气球为自己且在当前气球上抬起触控则显示当前气球内容                      //显示完内容后清空当前气球                  currentBallon=null;                       showWindow=!showWindow;                                    List<Overlay> overlays = mv.getOverlays();                  overlays.remove(this);//删除此气球再添加                  overlays.add(this);//此气球就位于最上面了                  for(Overlay ol:overlays){//清除其他气球的showWindow标记                      if(ol instanceof MyBallonOverlay){                          if(ol!=this){                              ((MyBallonOverlay)ol).showWindow=false;                          }                                               }                  }                  return true;              }              else if(currentBallon==this){                  //若当前气球为自己但抬起触控不再自己上则清空气球状态并返回true                  currentBallon=null;                  return true;                              }                      }          return false;      }      @Override      public void draw(Canvas canvas, MapView mapView, boolean shadow) {                      //将经纬度翻译成屏幕上的XY坐标          Point p= getPoint(mapView);                        //在坐标指定位置绘制气球          canvas.drawBitmap(MainActivity.bitmap, p.x-picWidth/2, p.y-picHeight, null);                    if(showWindow){//如果showWindow为true则显示信息窗口              drawWindow(canvas,p,160);          }          //调用父类绘制          super.draw(canvas, mapView, shadow);      }            public Point getPoint(MapView mapView){//将经纬度翻译成屏幕上的XY坐标          Projection projettion = mapView.getProjection();          Point p = new Point();          projettion.toPixels(gp, p);          return p;      }            public void drawWindow(Canvas canvas,Point p,int winWidth){//绘制信息窗口的方法          int charSize=15;          int textSize=16;          int leftRightPadding=2;                    //为信息分行          int lineWidth=winWidth-leftRightPadding*2;//每行的宽度          int lineCharCount=lineWidth/(charSize);    //每行字符数          //扫描整个信息字符串分行          ArrayList<String> alRows=new ArrayList<String>();          String currentRow="";          for(int i=0;i<msg.length();i++){                          char c=msg.charAt(i);              if(c!='\n'){                  currentRow=currentRow+c;              }              else{                  if(currentRow.length()>0){                      alRows.add(currentRow);                  }                                  currentRow="";              }              if(currentRow.length()==lineCharCount){                  alRows.add(currentRow);                  currentRow="";              }          }          if(currentRow.length()>0){              alRows.add(currentRow);          }          int lineCount=alRows.size();//总行数          int winHeight=lineCount*(charSize)+2*arcR;//窗体高度          //创建paint对象          Paint paint=new Paint();          paint.setAntiAlias(true);          paint.setTextSize(textSize);              //绘制 信息窗体圆角矩形          paint.setARGB(255, 255,251,239);          int x1=p.x-winWidth/2;          int y1=p.y-picHeight-winHeight-1;          int x2=x1+winWidth;          int y2=y1+winHeight;                  RectF r=new RectF(x1,y1,x2,y2);                  canvas.drawRoundRect(r, arcR, arcR, paint);          paint.setARGB(255,198,195,198);          paint.setStyle(Paint.Style.STROKE);          paint.setStrokeWidth(2);          canvas.drawRoundRect(r, arcR, arcR, paint);                    //循环绘制每行文字          paint.setStrokeWidth(0);          paint.setARGB(255, 10, 10, 10);                  int lineY=y1+arcR+charSize;          for(String lineStr:alRows){      System.out.println("lineStr"+lineStr);                      for(int j=0;j<lineStr.length();j++){                  String colChar=lineStr.charAt(j)+"";                  canvas.drawText(colChar, x1+leftRightPadding+j*charSize, lineY, paint);              }              lineY=lineY+charSize;          }      }  }

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

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