Android 使用Runnable+;位图标记动画的Handler.postdayed

Android 使用Runnable+;位图标记动画的Handler.postdayed,android,animation,android-maps,Android,Animation,Android Maps,我想在MapActivity的覆盖图中放置一个动画标记,显示用户的当前位置。我需要能够打开和关闭动画。我认为这可以通过以下方式实现: /** * Class to display current location marker above MapActivity */ public class MyLocationOverlay extends Overlay { private Canvas canvas; private final Handler handler =

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

/**
 * 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()调用构造函数

并且动画/绘制由调用

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

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

好的,回答我自己的问题–关键在于
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()
方法记录画布、地图视图和位置感觉有点困难,但这可能是唯一的方法…

好的,回答我自己的问题–关键在于
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()
方法记录画布、地图视图和位置感觉有点笨拙,但这可能是唯一的方法