2011年1月12日水曜日

Google マップの ItemizedOverlay でアイコンが表示されない現象について

android developers の以下のサイトですが、

Hello View, Google Map View
http://developer.android.com/resources/tutorials/views/hello-mapview.html


ItemizedOverlay の派生クラスである HelloItemizedOverlay に、
コンストラクタが2つ定義されています。

boundCenterBottom()を使用するコンストラクタ
 public HelloItemizedOverlay(Drawable defaultMarker) {
     super(boundCenterBottom(defaultMarker));
 }
boundCenterBottom()を使用しないコンストラクタ
 public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
     super(defaultMarker);
     mContext = context;
 }

このうち、boundCenterBottom()を使用しないコンストラクタを使用すると、
アイコン(ドロイド君)が表示されません (つω・。)うぅぅ…

HelloItemizedOverlay.java
package jp.kochi.GoogleMapOverlayTest;

import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;

public class HelloItemizedOverlay extends ItemizedOverlay<OverlayItem> {

  private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
  private Context mContext;

  public HelloItemizedOverlay(Drawable defaultMarker) {
    super(boundCenterBottom(defaultMarker));
  }

  public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
    super(defaultMarker);
    mContext = context;
  }
  @Override
  protected OverlayItem createItem(int i) {
    return mOverlays.get(i);
  }

  @Override
  public int size() {
    return mOverlays.size();
  }

  public void addOverlay(OverlayItem overlay) {
    mOverlays.add(overlay);
    populate();
  }

  @Override
  protected boolean onTap(int index) {
    OverlayItem item = mOverlays.get(index);
    AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
    dialog.setTitle(item.getTitle());
    dialog.setMessage(item.getSnippet());
    dialog.show();
    return true;
  }

}


GoogleMapOverlayTestActivity.java
package jp.kochi.GoogleMapOverlayTest;

import java.util.List;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import android.graphics.drawable.Drawable;
import android.os.Bundle;

public class GoogleMapOverlayTestActivity extends MapActivity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    MapView mapView = (MapView) findViewById(R.id.mapview);

    // ビルドイン-ズームコントローラー使用
    mapView.setBuiltInZoomControls(true);

    // 航空写真モードに変更
    mapView.setSatellite(true);

    // Droidアイコン表示
    List<Overlay> mapOverlays = mapView.getOverlays();
    Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker);
    
    // こっちは表示される。
    HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable);

    // こっちだと表示されない。
    // HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable, GoogleMapOverlayTestActivity.this);
    GeoPoint point = new GeoPoint(19240000,-99120000);
    OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!");

    itemizedoverlay.addOverlay(overlayitem);
    mapOverlays.add(itemizedoverlay);

  }

 @Override
 protected boolean isRouteDisplayed() {
  // TODO Auto-generated method stub
  return false;
 }
}


、なんでか~?と調べたところ、

そもそも Drawable に対し、setBounds() の実行が必要で、
直接、Drawable に対し、setBounds() を実行するか、または、
boundCenter() または boundCenterBottom() を実行する必要があるようです。

Drawable より抜粋
The setBounds(Rect) method must be called to tell the Drawable where it is drawn and how large it should be. All Drawables should respect the requested size, often simply by scaling their imagery. A client can find the preferred size for some Drawables with the getIntrinsicHeight() and getIntrinsicWidth() methods.

対応としては、素直に、boundCenter() または boundCenterBottom() を使えばよいと思うのですが、
setBounds() を使用する方法でも構いません。

GoogleMapOverlayTestActivity.java の抜粋 (setBounds()の修正案)
// setBounds追加すると表示される。
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable, GoogleMapOverlayTestActivity.this);