将叠加层添加到 OSMDROID

Posted

技术标签:

【中文标题】将叠加层添加到 OSMDROID【英文标题】:Adding Overlay to OSMDROID 【发布时间】:2011-09-23 16:37:54 【问题描述】:

我已经为此苦苦挣扎了很长时间。 我正在尝试在我的地图上添加叠加层。 我正在使用开源 OSMdroid。但我从这个例子中得到的只是从一个角落到另一个角落的直线红线。 我的目标是在我的 geoPoint 设置位置添加一些图标。

这是我的代码:

 package osmdemo.demo;

import java.util.List;

import microsoft.mappoint.TileSystem;

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;
import org.osmdroid.views.MapView.Projection;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.ScaleBarOverlay;
import org.osmdroid.views.util.constants.MapViewConstants;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.location.LocationManager;
import android.os.Bundle;

public class map extends Activity implements MapViewConstants


    /** Called when the activity is first created. */

    protected static final String PROVIDER_NAME = LocationManager.GPS_PROVIDER;
    MapController mapController;
    MapView mapView;
    ScaleBarOverlay mScaleBarOverlay;
    private MapOverlay mmapOverlay = null;
    private LocationManager mLocMgr;

    @Override
    public void onCreate(Bundle savedInstanceState)
    

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mapView = (MapView) findViewById(R.id.mapview);

        mapView.setTileSource(TileSourceFactory.MAPNIK);
        mapView.setBuiltInZoomControls(true);
        mapView.setMultiTouchControls(true);

        mapController = mapView.getController();
        mapController.setZoom(20);
        GeoPoint point2 = new GeoPoint(31.987968, 34.783069);
        mapController.setCenter(point2);

        this.mmapOverlay = new MapOverlay(this);

        List<Overlay> listOfOverlays = mapView.getOverlays();
        listOfOverlays.add(mmapOverlay);
        mapView.invalidate();
    

    public class MapOverlay extends org.osmdroid.views.overlay.Overlay
    

        public MapOverlay(Context ctx)
        
            super(ctx);
            // TODO Auto-generated constructor stub
        

        @Override
        protected void draw(Canvas pC, MapView pOsmv, boolean shadow)
        
            if (shadow)
                return;

            Paint lp3;
            lp3 = new Paint();
            lp3.setColor(Color.RED);
            lp3.setAntiAlias(true);
            lp3.setStyle(Style.STROKE);
            lp3.setStrokeWidth(1);
            lp3.setTextAlign(Paint.Align.LEFT);
            lp3.setTextSize(12);
            // Calculate the half-world size
            final Rect viewportRect = new Rect();
            final Projection projection = pOsmv.getProjection();
            final int zoomLevel = projection.getZoomLevel();
            int mWorldSize_2 = TileSystem.MapSize(zoomLevel) / 2;

            // Save the Mercator coordinates of what is on the screen
            viewportRect.set(projection.getScreenRect());
            // DON'T set offset with either of below
            // viewportRect.offset(-mWorldSize_2, -mWorldSize_2);
            // viewportRect.offset(mWorldSize_2, mWorldSize_2);

            // Draw a line from one corner to the other
            pC.drawLine(viewportRect.left, viewportRect.top,
                    viewportRect.right, viewportRect.bottom, lp3);
        

        public void onProviderDisabled(String arg0)
        
        

        public void onProviderEnabled(String provider)
        
        

    


这是我的清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.overlay" android:versionCode="1" android:versionName="1.0">
    <uses-sdk android:minSdkVersion="3" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


    <application >
        <activity android:name=".OverlayDemo" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

提前致谢,

射线。

【问题讨论】:

您能更具体地说明您要做什么吗?您是否尝试在地理点添加图标?您是否尝试进行自定义绘图? 我正在尝试在地理点添加一个图标! ! 【参考方案1】:

自编写示例代码以来,jar 版本 3.0.3 和 3.0.4 似乎发生了一些变化。

如果您的应用基于上一个答案中引用的代码,请更改行

mResourceProxy = new ResourceProxyImpl(getApplicationContext());

mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());

这至少应该让您使用默认图标。

编辑

这应该使地图位于利物浦东北部的中心,并在中心之外放置一个图标。

package osmdemo.demo;

import java.util.ArrayList;
import org.osmdroid.DefaultResourceProxyImpl;
import org.osmdroid.ResourceProxy;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapController;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.ItemizedOverlay;
import org.osmdroid.views.overlay.OverlayItem;
import org.osmdroid.views.util.constants.MapViewConstants;

import android.app.Activity;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.Toast;

public class DemoMap extends Activity implements LocationListener,
        MapViewConstants 

    private MapView mMapView;
    private MapController mapController;
    private LocationManager mLocMgr;
    private ItemizedOverlay<OverlayItem> mMyLocationOverlay;
    private ResourceProxy mResourceProxy;

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

        mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
        setContentView(R.layout.copymain);

        mMapView = (MapView) this.findViewById(R.id.mapview);
        mMapView.setTileSource(TileSourceFactory.MAPNIK);
        mMapView.setBuiltInZoomControls(true);
        mMapView.setMultiTouchControls(true);
        mapController = this.mMapView.getController();
        mapController.setZoom(15);
        GeoPoint point2 = new GeoPoint(53554070, -2959520); // centre map here
        GeoPoint point3 = new GeoPoint(53554070 + 1000, -2959520 + 1000); // icon goes here
        mapController.setCenter(point2);
        mLocMgr = (LocationManager) getSystemService(LOCATION_SERVICE);
        mLocMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 100,
                this);

        ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
        // Put overlay icon a little way from map centre
        items.add(new OverlayItem("Here", "SampleDescription", point3));

        /* OnTapListener for the Markers, shows a simple Toast. */
        this.mMyLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
                new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() 
                    @Override
                    public boolean onItemSingleTapUp(final int index,
                            final OverlayItem item) 
                        Toast.makeText(
                                DemoMap.this,
                                "Item '" + item.mTitle, Toast.LENGTH_LONG).show();
                        return true; // We 'handled' this event.
                    
                    @Override
                    public boolean onItemLongPress(final int index,
                            final OverlayItem item) 
                        Toast.makeText(
                                DemoMap.this, 
                                "Item '" + item.mTitle ,Toast.LENGTH_LONG).show();
                        return false;
                    
                , mResourceProxy);
        this.mMapView.getOverlays().add(this.mMyLocationOverlay);
        mMapView.invalidate();
    

    public void onLocationChanged(Location location) 
        int lat = (int) (location.getLatitude() * 1E6);
        int lng = (int) (location.getLongitude() * 1E6);
        GeoPoint gpt = new GeoPoint(lat, lng);
        mapController.setCenter(gpt);
        mMapView.invalidate();
    

    @Override
    public void onProviderDisabled(String arg0) 
    @Override
    public void onProviderEnabled(String provider) 
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) 


它有点粗糙和准备好了,但至少它运行良好,只有 3.0.4 jar 和 slf4j 一个。希望对您有所帮助。

编辑 2

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="osmdemo.demo"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name="DemoMap"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="3" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

</manifest> 

.

【讨论】:

是的,我已将其更改为 DefaultResoursseProxyImpl 但我仍然收到此错误:06-30 15:48:55.153: ERROR/AndroidRuntime(11997): FATAL EXCEPTION: main 06-30 15:48: 55.153:错误/AndroidRuntime(11997):java.lang.RuntimeException:无法实例化活动 ComponentInfocom.test.overlay/com.test.overlay.OverlayDemo:java.lang.ClassNotFoundException:com.test.overlay.OverlayDemo loader dalvik.system.PathClassLoader[/data/app/com.test.overlay-2.apk] ... 也许我需要在构建路径中添加更多的罐子?目前我使用这些:APACHEMIME ver:47.0.4, HTTPMIME ver:4.0 beta1, osmdroid3.0.4.jar slf4j ver:1.5.8 不,我刚刚得到了你所拥有的 sl4j 和 osmdroid 版本。我会看看我是否可以将我的代码减少到最低限度以显示覆盖并将其发布到我的答案中。 谢谢你,我为此苦苦挣扎了好几天! 仍然与 ClassNotFoundException 相同的错误。我在这里错过了什么?【参考方案2】:

如果您尝试添加图标,那么您需要查看 ItemizedOverlay 类。您可以使用 osmdroid 的 ItemizedIconOverlay,它是 ItemizedOverlay 的具体实现,或者您可以自己继承 ItemizedOverlay。看看样本,例如:

http://code.google.com/p/osmdroid/source/browse/trunk/OpenStreetMapViewer/src/org/osmdroid/samples/SampleWithMinimapItemizedoverlay.java

【讨论】:

我找到了那个例子:code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/…。但我不明白如何将它集成到我的代码中?我的地图将如何在其中使用它? 我在答案中添加了一个样本,应该会有所帮助。 它需要类 ResourceProxyImpl。所以我把它取自:google.com/codesearch#OOgMjZrCM0A/trunk/OpenStreetMapViewer/src/…。但我在运行时收到此错误:无法实例化活动 ComponentInfocom.test.overlay/com.test.overlay.OverlayDemo: java.lang.ClassNotFoundException: com.test.overlay.OverlayDemo in loader dalvik.system.PathClassLoader [ /data/app/com.test.overlay-1.apk] 有什么想法吗?谢谢。【参考方案3】:

@雷曼

请再做一件事。当地图位置发生变化时 确实发生了变化,但图标消失了。我如何验证图标到 新变化? – rayman 2011 年 7 月 1 日 7:12

这是您的位置发生变化的地方

public void onLocationChanged(Location location) 
    int lat = (int) (location.getLatitude() * 1E6);
    int lng = (int) (location.getLongitude() * 1E6);
    GeoPoint gpt = new GeoPoint(lat, lng);
    mapController.setCenter(gpt);
    mMapView.invalidate();

但正如您所见,它不会向叠加层添加新图标。

你应该清除以前的项目

items.clear()

(如果您希望在创建新图标时删除“旧”图标),然后将新点 (gpt) 添加到项目。

items.add(new OverlayItem("Title", "Description", gpt));

等等……

【讨论】:

以上是关于将叠加层添加到 OSMDROID的主要内容,如果未能解决你的问题,请参考以下文章

如何将内容加载到类似灯箱的叠加层中

如何为 UIButton 创建动态叠加层?

错误 [IRForTarget]:在向 MKMapView 添加叠加层时找不到 Objective-C 间接 ivar 符号

将日/夜叠加层添加到带有MVC框架的Google地图中

在 osmdroid 中将叠加添加到 MapView

将图像裁剪为叠加层的形状 - iOS