自定義開發氣球com.google.android.maps.Overlay
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方法來繪制氣球對應的信息窗口。這個自定義的氣球可以服務于
大部分涉及到谷歌地圖的應用,我有很多應用的涉及到了這些代碼,很是實用。 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!