2010-07-26 35 views
1

我想在MapActivity上的Overlay上放置一个显示用户当前位置的动画标记。我需要能够打开和关闭动画。我想这可能如下实现:使用Runnable + Handler.postDelayed进行位图标记动画的问题

/** 
* 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()方法似乎永远不会被调用。我究竟做错了什么?

回答

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()方法的位置,但它可能是唯一的方法...