Android自定義氣球Overlay的開發

fmms 12年前發布 | 28K 次閱讀 Android Android開發 移動開發

    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; } } }</pre>

上述的draw方法完成了在指定的未知繪制氣球圖片,并根據氣球信息窗口的標志值來決定是否調用drawWindow方法來繪制氣球對應的信息窗口。這個自定義的氣球可以服務于

大部分涉及到谷歌地圖的應用,我有很多應用的涉及到了這些代碼,很是實用。

來自:http://blog.csdn.net/itachi85/article/details/6757052

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!