2015-07-10 52 views
2

我正在使用OSMdroid与离线MBTiles。我需要能够添加用户从ListView中选择多个MBtiles。 ListView窗户很容易。不过,我需要帮助获取基于从ListView中选择的MBtiles加载的不同MBtiles。我的MBTiles从SDCard加载。OSMdroid通过ListView加载多个离线MBTIles

import org.osmdroid.util.GeoPoint; 
import org.osmdroid.views.MapController; 
import org.osmdroid.views.MapView; 

import android.app.Activity; 
import android.os.Bundle; 
import android.widget.RelativeLayout; 

public class OfflineMapDemoActivity extends Activity { 

    private String MapName; 

    public String getMapName(){ 
     return MapName; 
    } 
    public void setMapName(String s){ 
     MapName = s; 
    } 

    // layout 
    private RelativeLayout mapLayout; 

    // MapView 
    private MapView mapView; 
    private MapController mapController; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 


     // init Layout 
     setContentView(R.layout.main); 
     this.mapLayout = (RelativeLayout) findViewById(R.id.mapLayout); 

     // init Offline Map 
     MapName="World.sqlitedb"; 
     this.mapView = new OfflineMapView(this, MapName); 
     this.mapController = mapView.getController(); 

     // set Zoom Countrol 
     this.mapView.setBuiltInZoomControls(true); 
     // set Touch Control 
     this.mapView.setMultiTouchControls(true); 
     // zoom to 15 
     this.mapController.setZoom(15); 
     //add mapview 
     this.mapLayout.addView(this.mapView, new RelativeLayout.LayoutParams(
        android.view.ViewGroup.LayoutParams.FILL_PARENT, 
        android.view.ViewGroup.LayoutParams.FILL_PARENT)); 

     // scroll to 24082456, 120558472 
     GeoPoint geoPoint = new GeoPoint(24082456, 120558472); 
     this.mapController.setCenter(geoPoint); 

    } 
} 

我创建一个全局字符串变量来保存MapName其中Listview类可以通过公共的方法setMapName()设置。

顺便说一下,有没有一种方法来自动读取MBTiles中心,而不是像这样的硬编码?

// scroll to 24082456, 120558472 
    GeoPoint geoPoint = new GeoPoint(24082456, 120558472); 
    this.mapController.setCenter(geoPoint); 

我应该使用每次用户切换哪种方法OSMdroid地图从ListView所选从列表视图离线MBtiles地图加载?上面的Create方法仅在第一次加载时加载MBTiles映射一次?这是列表视图代码。

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 

import android.app.ListActivity; 
import android.os.Bundle; 
import android.widget.SimpleAdapter; 

public class MyTwoListItemsActivity extends ListActivity { 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ArrayList<Map<String, String>> list = buildData(); 
     String[] from = { "mapname", "selected" }; 
     int[] to = { android.R.id.text1, android.R.id.text2 }; 

     SimpleAdapter adapter = new SimpleAdapter(this, list, 
      android.R.layout.simple_list_item_2, from, to); 
     setListAdapter(adapter); 
    } 

    private ArrayList<Map<String, String>> buildData() { 
     ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>(); 
     list.add(putData("Map1", "Map1")); 
     list.add(putData("Map2", "Map2")); 
     list.add(putData("Map3", "Map3")); 
     return list; 
    } 

    private HashMap<String, String> putData(String name, String purpose) { 
     HashMap<String, String> item = new HashMap<String, String>(); 
     item.put("mapname", mapname); 
     item.put("selected", selected); 
     return item; 
    } 

} 

如何整合MyTwoListItemsActivityOfflineMapDemoActivity之间切换?

回答

4

小世界,我只是做了你正在寻找的东西。它需要一个patch osmdroid。

假设应用了补丁,您需要制作自己的MapTileProviderBase扩展(请参阅MapTileProviderBasic作为参考)。你需要创建一个构造函数来接收一个文件数组,然后将其传递给FileArchiveProvider。从这里开始,一旦用户选择了他们想要用于离线地图的文件,然后将该列表传递给自定义tile提供程序的实例,然后调用MapView.setTileProvider。

还要注意的是,如果你的设备是奇巧和文件/ SD卡/ osmdroid工作得很好,为了这个目的,但是在/存储/ extSdCard(如三星设备),你需要还需要this

我最终会提交一些适配器的pull请求,这些适配器是为了使这个过程更简单。

编辑:您的直接问题“我如何整合MyTwoListItemsActivity和OfflineMapDemoActivity之间的切换?”,更多的是关于如何将数据从一个活动转移到另一个活动的android特定问题。意向和共享偏好是这个应用程序最可能的候选者。您可能需要考虑使用某种弹出式菜单,菜单,操作栏,对话框等来翻转地图来源。 MapView的构建很昂贵,并且防止重新初始化将是一个好主意。

编辑:这是我使用的代码。

注意事项1)您需要提前知道每个存档的Tile Source名称。 Zip文件通常是地图源名称,如OpenStreetMaps。 Sqlite有一个列,如果你的瓷砖没有出现,这是最可能的原因。

创建瓷砖来源。为了简单起见,我选择将文件命名为准确映射文件源名称。调整以满足您的需求。

public class FileBasedTileSource extends XYTileSource { 

    public FileBasedTileSource(String aName, ResourceProxy.string aResourceId, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding, String[] aBaseUrl) { 
     super(aName, aResourceId, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding, aBaseUrl); 
    } 

    public static ITileSource getSource(String name) { 
     if (name.contains(".")) { 
      name = name.substring(0, name.indexOf(".")); 
     } 
     return new FileBasedTileSource(name, 
      ResourceProxy.string.mapbox, 0, 18, 256, ".png", new String[]{ 
      "http://localhost"}); 
    } 
} 

,那么你会用

ITileSource src=FileBasedTileSource.getSource("MyTileSource.gemf"); 

下一页创建它,你需要下面的类,我将创建一个拉请求。这是瓷砖供应商。

public class OfflineTileProvider extends MapTileProviderArray implements IMapTileProviderCallback { 

    /** 
    * Creates a {@link MapTileProviderBasic}. 
    * throws with the source[] is null or empty 
    */ 
    public OfflineTileProvider(final IRegisterReceiver pRegisterReceiver, File[] source 
    ) 
     throws Exception { 
     super(FileBasedTileSource.getSource(source[0].getName()), pRegisterReceiver); 
     IArchiveFile[] f = new IArchiveFile[source.length]; 
     for (int i=0; i < source.length; i++) 
      f[i]=ArchiveFileFactory.getArchiveFile(source[i]); 

     mTileProviderList.add(new MapTileFileArchiveProvider(pRegisterReceiver, getTileSource(), f)); 

    } 
} 

然后如下创建一个实例:

OfflineTileProvider provider = new OfflineTileProvider(new SimpleRegisterReceiver(mContext), myUserSelectedFiles[])); 
mMapView.setTileProvider(provider); 
mMapView.setUseDataConnection(false); 
mMapView.invalidate(); 

这应该创建一个实例并更新地图视图。

其他注意事项:IO异常超过可能

+0

可你能分享您使用支持多个MBTiles你的代码?非常感激。 – user914425

+0

更新了代码。此代码不需要除两个链接问题外的osm修改 – spy

+0

osmdroid问题参考https://github.com/osmdroid/osmdroid/issues/140 – spy