android google map中使用mapView適應多個地表徵圖識

來源:互聯網
上載者:User

遇到一個需求,在地圖中標識多個地點(全國範圍),地點的gps放到一個xml檔案中,以便隨時修改。要求是地圖要儘可能詳細,但是得把所有地點包括在內。
做法如下:
1、先得到資料的最大和最小經緯度,計算出資料的中心點(也是經緯度);
2、把地圖的zoom level預設一個比較大的值,如19或20之類的。這樣的話肯定是有很多地點是沒有顯示在mapView上的,然後再逐漸減少level的值,以顯示所有的地點。
    過程很清晰,看起來沒什麼問題,得出主要代碼如下:
Java代碼 
public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        comList = this.getComList();//擷取網路攝影機資料 
        mapView = (MapView) findViewById(R.id.MapView01); 
        mapView.setStreetView(true); 
        mapView.setEnabled(true); 
        mapView.setClickable(true); 
        mapView.setBuiltInZoomControls(true); // 設定地圖支援縮放 
         
        System.out.println("長和寬:"+mapView.getHeight()+","+mapView.getWidth()); 
        mapController = (MapController)mapView.getController(); 
//      locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);// 位置管理器 
 
        // 設定地圖中心點 
        Double lat1 = (min_y + max_y) / 2 * 1E6; 
        Double lng1 = (min_x + max_x) / 2 * 1E6; 
        System.out.println("中心點:"+lat1+","+lng1); 
        GeoPoint geoPoint = new GeoPoint(lat1.intValue(), lng1.intValue()); 
        mapController.setCenter(geoPoint); 
        mapController.setZoom(16); 
         
        ... 
 
        Drawable defaultMarker = getResources().getDrawable(R.drawable.arrow); 
        Drawable activeMarker = getResources().getDrawable(R.drawable.icon); 
        defaultMarker.setBounds(0, 0, defaultMarker.getMinimumWidth(), 
                defaultMarker.getMinimumHeight()); 
        PositionsOverlay posOverlay = new PositionsOverlay(defaultMarker, 
                comList, activeMarker,this); 
        List<Overlay> overlays = getMapView().getOverlays(); 
        overlays.add(posOverlay); 
         
         
        //根據左上方來判斷 
        Projection proj = mapView.getProjection(); 
        MapController mapController = mapView.getController(); 
        GeoPoint geoFromPix = proj.fromPixels(0, 0);//  
        double pix_lng = geoFromPix.getLongitudeE6() / 1E6;// 左上方螢幕像素轉換成的gps經度 
        double pix_lat = geoFromPix.getLatitudeE6() / 1E6;// 左上方螢幕像素轉換成的gps緯度 
 
        // System.out.println("縮放前中心點: "+mapView.getMapCenter()); 
        while (min_x < pix_lng) {// 資料中最小經度如果小於螢幕所對應的最小經度(出界),則縮小地圖,讓資料顯示到螢幕中 
            System.out.println("縮小地圖1:" + min_x + "," + pix_lng); 
            mapController.setZoom(mapView.getZoomLevel() - 1); 
            pix_lng = mapView.getProjection().fromPixels(0, 0) 
                    .getLongitudeE6() / 1E6; 
            pix_lat = mapView.getProjection().fromPixels(0, 0) 
                    .getLatitudeE6() / 1E6; 
 
        } 
        while (max_y > pix_lat) {// 資料中最大緯度如果大於螢幕所對應的最小緯度(出界),則縮小地圖,讓資料顯示到螢幕中 
            System.out.println("縮小地圖2"); 
            mapController.setZoom(mapView.getZoomLevel() - 1); 
            pix_lat = mapView.getProjection().fromPixels(0, 0) 
                    .getLatitudeE6() / 1E6; 
        } 


運行結果,後台狂刷:
Java代碼 
08-18 07:47:00.076: INFO/System.out(437): 縮小地圖1:121.1004,121.145444 
08-18 07:47:00.076: INFO/System.out(437): 縮小地圖1:121.1004,121.145444 
08-18 07:47:00.076: INFO/System.out(437): 縮小地圖1:121.1004,121.145444 
08-18 07:47:00.076: INFO/System.out(437): 縮小地圖1:121.1004,121.145444 
08-18 07:47:00.076: INFO/System.out(437): 縮小地圖1:121.1004,121.145444 
08-18 07:47:00.076: INFO/System.out(437): 縮小地圖1:121.1004,121.145444 


將左上方換成右下角,發現取不到mapView的寬和高。。。
上網找了下,說法如下:
Java代碼 
A common mistake made by new Android developers is to use 
the width and height of a view inside its constructor. When 
a view’s constructor is called, Android doesn’t know yet how 
big the view will be, so the sizes are set to zero. The real sizes 
are calculated during the layout stage, which occurs after 
construction but before anything is drawn. You can use the 
onSizeChanged( )method to be notified of the values when they 
are known, or you can use the getWidth( ) and getHeight( )methods 
later, such as in the onDraw( ) method 

http://www.coderanch.com/t/435390/Android/Mobile/screen-size-at-run-time
要等開始布局時才能得到寬和高等特性?這麼說的話使用
Java代碼 
pix_lng = mapView.getProjection().fromPixels(0, 0) 
                    .getLongitudeE6() / 1E6; 

也是沒意義的了。。。
這樣的話只能等mapView渲染完畢才能處理了.
本來想使用mapView的draw方法來處理,但是無從下手(繼承mapView類來重寫draw方法?),只好寫了個線程,監聽mapView是否完成(完成的話height和width都不會等0了),然後把剛才那段代碼放到線程裡,成功了。。。
新線程代碼:

Java代碼 
public void run() { 
        while (mapView.getHeight() == 0) { 
            System.out.println("mapView等於0,mapView還沒渲染完畢"); 
            try { 
                Thread.currentThread().sleep(100); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
        } 
        if (mapView.getHeight() != 0) { 
            /*
             * 使用setZoom來讓資料標籤自適應螢幕
             */ 
 
            //根據左上方來判斷 
            Projection proj = mapView.getProjection(); 
            MapController mapController = mapView.getController(); 
            GeoPoint geoFromPix = proj.fromPixels(0, 0);//  
            double pix_lng = geoFromPix.getLongitudeE6() / 1E6;// 左上方螢幕像素轉換成的gps經度 
            double pix_lat = geoFromPix.getLatitudeE6() / 1E6;// 左上方螢幕像素轉換成的gps緯度 
 
            // System.out.println("縮放前中心點: "+mapView.getMapCenter()); 
            while (min_x < pix_lng) {// 資料中最小經度如果小於螢幕所對應的最小經度(出界),則縮小地圖,讓資料顯示到螢幕中 
                System.out.println("縮小地圖1:" + min_x + "," + pix_lng); 
                mapController.setZoom(mapView.getZoomLevel() - 1); 
                pix_lng = mapView.getProjection().fromPixels(0, 0) 
                        .getLongitudeE6() / 1E6; 
                pix_lat = mapView.getProjection().fromPixels(0, 0) 
                        .getLatitudeE6() / 1E6; 
 
            } 
            while (max_y > pix_lat) {// 資料中最大緯度如果大於螢幕所對應的最小緯度(出界),則縮小地圖,讓資料顯示到螢幕中 
                System.out.println("縮小地圖2"); 
                mapController.setZoom(mapView.getZoomLevel() - 1); 
                pix_lat = mapView.getProjection().fromPixels(0, 0) 
                        .getLatitudeE6() / 1E6; 
            } 
            System.out.println("mapView的值:" + mapView.getHeight()); 
        } 
    } 

剛才那段代碼改成:
Java代碼 
public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        comList = this.getComList();//擷取網路攝影機資料 
        mapView = (MapView) findViewById(R.id.MapView01); 
        mapView.setStreetView(true); 
        mapView.setEnabled(true); 
        mapView.setClickable(true); 
        mapView.setBuiltInZoomControls(true); // 設定地圖支援縮放 
         
        System.out.println("長和寬:"+mapView.getHeight()+","+mapView.getWidth()); 
        mapController = (MapController)mapView.getController(); 
//      locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);// 位置管理器 
 
        // 設定地圖中心點 
        Double lat1 = (min_y + max_y) / 2 * 1E6; 
        Double lng1 = (min_x + max_x) / 2 * 1E6; 
        System.out.println("中心點:"+lat1+","+lng1); 
        GeoPoint geoPoint = new GeoPoint(lat1.intValue(), lng1.intValue()); 
        mapController.setCenter(geoPoint); 
        mapController.setZoom(16); 
         
        ... 
 
        Drawable defaultMarker = getResources().getDrawable(R.drawable.arrow); 
        Drawable activeMarker = getResources().getDrawable(R.drawable.icon); 
        defaultMarker.setBounds(0, 0, defaultMarker.getMinimumWidth(), 
                defaultMarker.getMinimumHeight()); 
        PositionsOverlay posOverlay = new PositionsOverlay(defaultMarker, 
                comList, activeMarker,this); 
        List<Overlay> overlays = getMapView().getOverlays(); 
        overlays.add(posOverlay); 
         
         
        //啟動新的線程來監視mapView是否渲染完畢,渲染完畢則開始調整mapView的縮放水平以適合全部資料 
        SelfAdaptionMapView cv = new SelfAdaptionMapView(mapView,max_x,min_y,min_x,max_y); 
        new Thread(cv).start(); 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.