自定義開發氣球com.google.android.maps.Overlay

jopen 12年前發布 | 21K 次閱讀 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;
        }
    }
}

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

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

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