1

我想在 MapActivity 上的 Overlay 中放置一个显示用户当前位置的动画标记。我需要能够打开和关闭动画。我认为这可以通过以下方式完成:

/**
 * Class to display current location marker above MapActivity
 */
public class MyLocationOverlay extends Overlay {

    private Canvas canvas;
    private final Handler handler = new Handler();
    private Runnable runnable;
    private GeoPoint geoPoint;
    private int xMarker, yMarker;
    private int markerNumber = 0;
    private Bitmap marker, marker0, marker1, marker2, marker3;

    public MyLocationOverlay(Context context) {
        Resources r = context.getResources();
        marker0 = BitmapFactory.decodeResource(r, R.drawable.marker);
        marker1 = BitmapFactory.decodeResource(r, R.drawable.marker1);
        marker2 = BitmapFactory.decodeResource(r, R.drawable.marker2);
        marker3 = BitmapFactory.decodeResource(r, R.drawable.marker3);
        marker = marker0;
    }

    /** Sets location marker is to be drawn at */
    public void setLocation(GeoPoint geoPoint) {
        this.geoPoint = geoPoint;
    }

    /** Sets whether marker is to be animated or static */
    public void animateMarker(boolean on) {
        if (on) {    // activate animation
            if (runnable == null) runnable = new Runnable() {
                public void run() {
                    switch (markerNumber) {
                    case 0: marker = marker0; break;
                    case 1: marker = marker1; break;
                    case 2: marker = marker2; break;
                    case 3: marker = marker3; break;
                    }
                    markerNumber = ++markerNumber % 3;
                    canvas.drawBitmap(marker, xMarker, yMarker, null);
                    handler.postDelayed(this, 500);
                }
            };
        } else {    // cancel animation, make marker static version
            handler.removeCallbacks(runnable);
            runnable = null;
            marker = marker0;
        }
    }

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

            // convert the location to screen pixels         
            Point point = projection.toPixels(geoPoint, null);

            // record the canvas and the marker position for the animated marker
            this.canvas = canvas;
            xMarker = point.x - marker.getWidth()/2;
            yMarker = point.y - marker.getHeight()/2;

            // draw the marker centred at the location
            canvas.drawBitmap(marker, xMarker, yMarker, null);
        }
        super.draw(canvas, mapView, shadow);
    }

    @Override
    public boolean onTap(GeoPoint point, MapView mapView) { return false; }
}

使用从主 MapActivity.onResume() 调用构造函数

    locationOverlay = MyLocationOverlay(this)

并且动画/绘制由

    GeoPoint point = new GeoPoint(latE6, lonE6);
    locationOverlay.setLocation(point);
    locationOverlay.animateMarker(true);
    mapView.getController().animateTo(point);

但是,似乎从未调用 run() 方法。我究竟做错了什么?

4

1 回答 1

1

好的,回答我自己的问题——关键在于文档中Runnable.run():“这个方法在启动线程时调用,该线程是用实现 Runnable 的类创建的”。因为我是在线程启动后调用它,所以我需要通过调用来启动它Handler.postDelayed()

animateMarker() 方法现在看起来像这样:

public void animateMarker(boolean on) {
    if (on) {    // activate animation
        if (runnable == null) runnable = new Runnable() {
            public void run() {
                if (canvas!=null) {
                    switch (markerNumber) {
                    case 0: marker = marker0; break;
                    case 1: marker = marker1; break;
                    case 2: marker = marker2; break;
                    case 3: marker = marker3; break;
                    }
                    markerNumber = ++markerNumber % 4;
                    mapView.invalidate(xMarker, yMarker, 
                            xMarker+wMarker, yMarker+hMarker);
                }
                handler.postDelayed(this, 500);
            }
        };
        handler.postDelayed(runnable, 500);
    } else {    // cancel animation, make marker static version
        handler.removeCallbacks(runnable);
        runnable = null;
        marker = marker0;
    }
}

onDraw()方法中记录画布、地图视图和位置感觉有点笨拙,但这可能是唯一的方法......

于 2010-07-26T15:38:03.937 回答