iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
Mobile Development

[Android Studio & Spring boot 30天挑戰]系列 第 9

[Android Studio & Spring boot 30天挑戰] Day09- 離線地圖與線上地圖(下)

  • 分享至 

  • xImage
  •  

今天要接續來介紹離線地圖,我使用的離線地圖在Day07的時候有講過是台灣通用離線地圖,但是那個檔案只是單純的地圖檔,所以呢今天用了 osmdroid 這個第三方地圖套件做顯示!!

UI畫面

這個是離線地圖的畫面。
https://ithelp.ithome.com.tw/upload/images/20230819/20150369w9JYlGUFDT.png

程式碼

首先一樣要先加入 dependencies:

    implementation 'org.osmdroid:osmdroid-android:6.1.16'
    implementation 'org.osmdroid:osmdroid-mapsforge:6.1.16'

再來就可以在 layout檔加入了。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.map.OfflineMapFragment"
    android:background="@color/theme">

    <org.osmdroid.views.MapView
        android:id="@+id/offline_map_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </org.osmdroid.views.MapView>
</FrameLayout>

接下來就是我們 OfflineMapFragment:

剛開始要先初始化我們的地圖

private void init(View view) {
    // 初始化地圖視圖(MapView)
    mapView = (MapView) view.findViewById(R.id.offline_map_fragment);
    initOfflineMapOverlays(mapView); // 調用初始化離線地圖覆蓋物的方法
}

private void initOfflineMapOverlays(MapView mapView) {
    // 獲取地圖的最大和最小邊界
    final BoundingBox taiwanBounds = new BoundingBox(
            21.95, 122.9151, // 南西角座標:南緯20.5955度,東經122.9151度
            25.3581, 119.3277  // 北東角座標:北緯25.3581度,西經119.3277度
    );

    // 檢查是否已添加地圖覆蓋物,以避免重複添加
    if (mapView.getOverlays().size() <= 0) {
        mapViewOtherData(mapView); // 調用其他地圖設置方法
        mapView.setTileSource(TileSourceFactory.MAPNIK); // 設定地圖磚源為MAPNIK
        mapView.setDrawingCacheEnabled(true); // 啟用地圖繪製緩存
        mapView.setMinZoomLevel(9.9); // 設定地圖最小縮放級別
        mapView.setScrollableAreaLimitDouble(taiwanBounds); // 設定可滾動區域限制為台灣範圍
        mapView.getController().setZoom(9.9); // 設定地圖初始縮放級別
        mapView.getController().setCenter(new GeoPoint(21.95, 121)); // 設定地圖初始中心點座標
        mapView.setUseDataConnection(true); // 啟用使用數據連接
        mapView.setMultiTouchControls(true); // 啟用多點觸控縮放
        mapView.getOverlayManager().getTilesOverlay().setEnabled(true); // 啟用地圖磚覆蓋物
    }
}

最後就是把地圖檔轉換為地圖視圖,一樣加上註解。

public void mapViewOtherData(MapView mapView){
    // 定義離線地圖文件的文件名
    String fileName = "test.mbtiles";

    // 檢查離線地圖文件是否存在
    if (!file.exists()) {
        // 如果地圖文件不存在,設定地圖磚源為 MAPNIK(在線地圖)
        mapView.setTileSource(TileSourceFactory.MAPNIK);
    } else {
        // 如果地圖文件存在,解析文件擴展名
        fileName = fileName.substring(fileName.lastIndexOf(".") + 1);
        if (fileName.length() == 0)
            return;
        
        // 檢查文件擴展名是否已註冊為有效的地圖文件類型
        if (ArchiveFileFactory.isFileExtensionRegistered(fileName)) {
            try {
                // 創建離線磚提供者(OfflineTileProvider)
                OfflineTileProvider tileProvider = new OfflineTileProvider((IRegisterReceiver) new SimpleRegisterReceiver(context), new File[] { file });
                mapView.setTileProvider(tileProvider); // 設定地圖視圖的磚提供者
                
                String source = "";
                IArchiveFile[] archives = tileProvider.getArchives();
                if (archives.length > 0) {
                    // 獲取存檔文件中的磚源
                    Set<String> tileSources = archives[0].getTileSources();
                    if (!tileSources.isEmpty()) {
                        source = tileSources.iterator().next();
                        // 設定地圖視圖的磚源
                        mapView.setTileSource(FileBasedTileSource.getSource(source));
                    } else {
                        // 如果沒有磚源,設定地圖磚源為默認磚源
                        mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
                    }
                } else {
                    // 如果沒有存檔文件,設定地圖磚源為默認磚源
                    mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
                }
                
                mapView.invalidate(); // 刷新地圖視圖
                return;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

接下來下一片就要介紹最後一個摩斯密碼發送的功能了!!那明天見摟!!/images/emoticon/emoticon02.gif


上一篇
[Android Studio & Spring boot 30天挑戰] Day08- 離線地圖與線上地圖(中)
下一篇
[Android Studio & Spring boot 30天挑戰] Day10- 摩斯密碼發送(上)
系列文
[Android Studio & Spring boot 30天挑戰]30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言