在最大缩放级别平移地图视图时,GeoPoint和/或android.maps.Projection的奇怪行为

在最大缩放级别平移地图视图时,GeoPoint和/或android.maps.Projection的奇怪行为,android,Android,我遇到了一个奇怪的问题,即使用谷歌地图软件包获取点偏移 我有一个地图视图,上面显示了一条路线。我注意到,如果我一直放大,然后四处平移,我的路线会在靠近窗户边缘的地方被剪断。在对我自己的代码进行了大量调试之后,我发现即使是这样一个简单的例子也足以解决这个问题: GeoPoint midPoint = projection.fromPixels(mapView.getWidth()/2, mapView.getHeight()/2); GeoPoint

我遇到了一个奇怪的问题,即使用谷歌地图软件包获取点偏移

我有一个地图视图,上面显示了一条路线。我注意到,如果我一直放大,然后四处平移,我的路线会在靠近窗户边缘的地方被剪断。在对我自己的代码进行了大量调试之后,我发现即使是这样一个简单的例子也足以解决这个问题:

            GeoPoint midPoint = projection.fromPixels(mapView.getWidth()/2, mapView.getHeight()/2);
            GeoPoint nextPoint = new GeoPoint(midPoint.getLatitudeE6(), midPoint.getLongitudeE6());
            pathPaint.setColor(0xFF00FF00);
            projection.toPixels(midPoint, screenPoint);
            canvas.drawCircle(screenPoint.x, screenPoint.y, 5, pathPaint);
            pathPaint.setColor(0xFF0000FF);
            projection.toPixels(nextPoint, screenPoint);
            canvas.drawCircle(screenPoint.x, screenPoint.y, 5, pathPaint);
这将使用MapView.getProjection()返回的Projection类将像素坐标转换为地理点。然后使用相同的纬度/长度创建第二个地质点。最后,它将这两个地质点转换回屏幕坐标,并在此位置绘制两个圆,一个在另一个上

除此之外,当您四处平移时,第二个圆将从第一个圆偏移。它们具有相同的lat/lon坐标(我在绘图后检查),但最终被转换为不同的屏幕坐标。我的调试集中在水平平移上,但我相信垂直平移也会遇到类似的问题,这是基于我在原始应用程序代码中看到的情况

据我所知,由maps包创建的任何点都可以正常工作,但通过调用新的GeoPoint(lat,lon)创建的任何点都会表现出这种行为

我创建了一个简单的精简应用程序,展示了这种行为,粘贴在下面。(地图块不会下载,因为我没有费心签名,但你不需要它们来查看问题。)只需启动它,一直放大,然后开始向左或向右平移。观察绿点和蓝点的差异,并观察Log.d打印的状态,它们仍然具有相同的lat/lon

(是否有更好/首选的方式发布示例项目?对不起,这是我第一次在这里发布。)

src/example/mysample/mappoverlay.java:

package example.mysample;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.RadialGradient;
import android.graphics.Shader;
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.util.Log;

class MapOverlay extends Overlay
{
    public MapOverlay(MapScreen activity)
    {
        super();

        paint = new Paint();
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setAntiAlias(true);
    }

    @Override public boolean onTouchEvent(MotionEvent e, MapView mapView) {
        int motionAction = e.getAction();
        if ( motionAction == MotionEvent.ACTION_MOVE ) {
            dragging = true;
        }
        if ( motionAction == MotionEvent.ACTION_UP || motionAction == MotionEvent.ACTION_CANCEL ) {
            dragging = false;
        }
        return super.onTouchEvent(e, mapView);
    }

    @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) {
        if (!shadow && !dragging) {
            Projection projection = mapView.getProjection();

            // Draw two circles at the center
            // One with a virgin point, one that we constructed with the same coordinates
            GeoPoint midPoint = projection.fromPixels(mapView.getWidth()/2, mapView.getHeight()/2);
            GeoPoint nextPoint = new GeoPoint(midPoint.getLatitudeE6(), midPoint.getLongitudeE6());
            paint.setColor(0xFF00FF00);
            projection.toPixels(midPoint, screenPoint);
            canvas.drawCircle(screenPoint.x, screenPoint.y, 5, paint);
            paint.setColor(0xFF0000FF);
            projection.toPixels(nextPoint, screenPoint);
            canvas.drawCircle(screenPoint.x, screenPoint.y, 5, paint);

            // These print EQUAL.
            Log.d("BKC DEBUG", "Midpoint and our own midpoint have " +
                ((midPoint.getLatitudeE6() == nextPoint.getLatitudeE6()) ? "EQUAL" : "UNEQUAL") +
                " latitudes, and " +
                ((midPoint.getLongitudeE6() == nextPoint.getLongitudeE6()) ? "EQUAL" : "UNEQUAL") +
                " longitudes");
        }
    }

    private Paint paint;
    private boolean dragging;
    private Point screenPoint = new Point();

}
src/example/mysample/MapScreen.java:

package example.mysample;

import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import android.util.Log;

import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.GeoPoint;

public class MapScreen extends MapActivity
{

    @Override public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.map);

        mapView = (MapView)findViewById(R.id.map_map);
        mapView.setBuiltInZoomControls(true);
        mapView.getOverlays().add(new MapOverlay(this));

        MapController controller;
        controller = mapView.getController();
        controller.setZoom(17);
        controller.animateTo(new GeoPoint(36000000, -90000000));

    }

    @Override
    public boolean isRouteDisplayed() {
        return true;
    }

    private MapView mapView;

}
res/layout/map.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#414141"
    >    

 <com.google.android.maps.MapView
            android:id="@+id/map_map"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_marginLeft="3dip"
            android:layout_marginRight="3dip"
            android:layout_marginTop="3dip"
            android:layout_marginBottom="3dip"
            android:apiKey="0jPQdwUtQGBYfPALki6ghGG_X9Jpf-SllYckR4w"
            android:layout_centerInParent="true"
            android:clickable="true"
            />

</RelativeLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="example.mysample"
      android:versionCode="1"
      android:versionName="2.0.1">
    <uses-sdk android:minSdkVersion="4" />

    <!--uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /-->
    <!--uses-permission android:name="android.permission.READ_PHONE_STATE" /-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--uses-permission android:name="android.permission.WAKE_LOCK" /-->
    <!--uses-permission android:name="android.permission.READ_LOGS" /-->
    <!--uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /-->

    <!--application android:name="src.example.mysample.AppMain"
                 android:label="MySample"
                 android:icon="@drawable/icon_android"
                 android:theme="@android:style/Theme.NoTitleBar"
                 -->

    <application android:name="android.app.Application"
        android:label="MySample" >

        <uses-library android:name="com.google.android.maps"/>

        <!-- Main activity -->
        <activity android:name="example.mysample.MapScreen"
                  android:clearTaskOnLaunch="true"
                  android:label="MySample"
                  android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Other activities -->
        <!--activity android:name="example.mysample.SomethingElse"
                  android:label="Something"
                  android:screenOrientation="portrait"/-->

    </application>
</manifest>

build.xml(与模板相同):


我也面临这个问题-似乎是Android Mapview API中的一个bug-我认为Star面临的问题是:
评论中还包含了一个可能的解决方法,它很难看,但适用于。基本上,您可以确定错误并相应地调整结果

如果这对任何人都不适用,我也很想听听。谢谢——难看,但这看起来是目前最好的解决方案。
<?xml version="1.0" encoding="UTF-8"?>
<project name="PROJECT_NAME" default="help">

<!-- The local.properties file is created and updated by the 'android'
     tool.
     It contains the path to the SDK. It should *NOT* be checked into
     Version Control Systems. -->
    <property file="local.properties" />

    <!-- The build.properties file can be created by you and is never touched
         by the 'android' tool. This is the place to change some of the
         default property values used by the Ant rules.
         Here are some properties you may want to change/update:

         source.dir
             The name of the source directory. Default is 'src'.
         out.dir
             The name of the output directory. Default is 'bin'.

         Properties related to the SDK location or the project target should
         be updated using the 'android' tool with the 'update' action.

         This file is an integral part of the build system for your
         application and should be checked into Version Control Systems.

         -->
    <property file="build.properties" />

    <!-- The default.properties file is created and updated by the 'android'
         tool, as well as ADT.
         This file is an integral part of the build system for your
         application and should be checked into Version Control Systems. -->
    <property file="default.properties" />

    <!-- Custom Android task to deal with the project target, and import the
         proper rules.
         This requires ant 1.6.0 or above. -->
    <path id="android.antlibs">
        <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
        <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
        <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
    </path>

    <taskdef name="setup"
        classname="com.android.ant.SetupTask"
        classpathref="android.antlibs" />

<!-- extension targets. Uncomment the ones where you want to do custom work
     in between standard targets -->
<!--
    <target name="-pre-build">
    </target>
    <target name="-pre-compile">
    </target>

    [This is typically used for code obfuscation.
     Compiled code location: ${out.classes.absolute.dir}
     If this is not done in place, override ${out.dex.input.absolute.dir}]
    <target name="-post-compile">
    </target>
-->


    <!-- Execute the Android Setup task that will setup some properties
         specific to the target, and import the build rules files.

         The rules file is imported from
            <SDK>/platforms/<target_platform>/ant/ant_rules_r#.xml

         To customize existing targets, there are two options:
         - Customize only one target:
             - copy/paste the target into this file, *before* the
               <setup> task.
             - customize it to your needs.
         - Customize the whole script.
             - copy/paste the content of the rules files (minus the top node)
               into this file, *after* the <setup> task
             - disable the import of the rules by changing the setup task
               below to <setup import="false" />.
             - customize to your needs.
    -->
    <setup />

</project>