画像をアニメーションさせるサンプル・プログラムの2つ目です。
2つ目は、日本Androidの会のメーリング・リストでやりとりされていた
以下のスレッドを参考にさせて頂きました。
参考サイト: OverlayにImageViewを表示する方法について
参考サイトでは、OverlayItem を使用しているのですが、
表示させたい画像(アニメーション)は1つしかないので、Overlay を使用するようにしました。
<設計方針>
Overlay を使います。
Overlay の draw() で画像を表示させるわけですが、画像を60枚用意しておき、
draw() が実行される都度、画像を切り替えるようにしておきます。
(最後の画像になったら、最初の画像に戻ります)
MapView に対して定期的に invalidate() を実行することで、Overlay の draw() が定期的に
実行されるようになり、パラパラ漫画(アニメーション)の完成です。
Overlay の draw() で画像を表示させるわけですが、画像を60枚用意しておき、
draw() が実行される都度、画像を切り替えるようにしておきます。
(最後の画像になったら、最初の画像に戻ります)
MapView に対して定期的に invalidate() を実行することで、Overlay の draw() が定期的に
実行されるようになり、パラパラ漫画(アニメーション)の完成です。
<問題点>
問題点でないですが、MapView に対して invalidate() を実行しているため、
複数の画像(静止画)があった場合、それらも再描画対象となるかなぁというのが気にかかります。
複数の画像(静止画)があった場合、それらも再描画対象となるかなぁというのが気にかかります。
以下にポイントとなるソースを貼り付けます。
まずはレイアウトです。
FrameLayout に対し、MapView のみを表示させています。
(子要素が MapView しかないので、FrameLayout である必要はないんですけど。)
main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <com.google.android.maps.MapView android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:enabled="true" android:clickable="true" android:apiKey="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" /> </FrameLayout>
次は Activity (MapActivity継承) クラスです。
onCreate() では、person_01.png ~ person_60.png の 60 枚の画像を読み込んでいます。
その後、アニメーションを行う Overlay を MapView に紐付けています。
MapTestActivity.java
package jp.kochi.test; import java.util.ArrayList; import java.util.List; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.AnimationDrawable; import android.os.Bundle; import android.util.Log; import android.widget.ImageView; public class MapTestActivity extends MapActivity { ImageView mImageView; AnimationOverlay mAnimOverlay; @Override public void onCreate(Bundle savedInstanceState) { Log.v("MapTest", "onCreate()"); super.onCreate(savedInstanceState); setContentView(R.layout.main); MapView mapView = (MapView) findViewById(R.id.mapview); mapView.setBuiltInZoomControls(true); ArrayList<Bitmap> list = new ArrayList<Bitmap>(); Resources r = getResources(); int id; Bitmap bmp; String str; for (int i = 1; i <= 60; i++) { str = "person_" + String.format("%1$02d", i); id = r.getIdentifier(str, "drawable", getPackageName()); Log.v("MapTest", "str = " + str + ", id = " + id); bmp = BitmapFactory.decodeResource(r, id); list.add(bmp); } Log.v("MapTest", "list.size() = " + list.size()); // アニメーション表示 // お遍路さん2番札所 double latitude = 34.156028; double longitude = 134.49025; GeoPoint gpoint = new GeoPoint((int)(latitude * 1E6), (int)(longitude * 1E6)); List listOverlays = mapView.getOverlays(); mAnimOverlay = new AnimationOverlay(gpoint, list, mapView); listOverlays.add(mAnimOverlay); } @Override protected void onResume() { Log.v("MapTest", "onResume()"); super.onResume(); mAnimOverlay.resume(); } @Override protected void onPause() { Log.v("MapTest", "onPause()"); super.onPause(); mAnimOverlay.pause(); } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } }
onResume()、onPause() では、Overlay のアニメーション (定期的に invalidate() 実行) を
再開/停止させる処理を追加しています。
最後は AnimationOverlay (Overlay継承) クラスです。
AnimationOverlay.java
package jp.kochi.test; import java.util.ArrayList; import java.util.List; import android.R.bool; import android.R.drawable; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.util.Log; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.android.maps.Projection; public class AnimationOverlay extends Overlay implements Runnable { private Handler mHandler; private ArrayList<Bitmap> mPngList; private int current_frame; private MapView mMapView; private GeoPoint mGeoPoint; final private int sInterval = 100; private boolean mStop = false; public AnimationOverlay(GeoPoint point, ArrayList<Bitmap> list, MapView mview) { Log.v("MapTest", "AnimationOverlay()"); mPngList = list; mMapView = mview; mGeoPoint = point; current_frame = 0; mHandler = new Handler(); mHandler.postDelayed(this, sInterval); } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, shadow); if (shadow == false) { Log.v("MapTest", "draw() : shadow = false"); Point pxPoint = new Point(); Projection projection = mMapView.getProjection(); projection.toPixels(mGeoPoint, pxPoint); canvas.drawBitmap(mPngList.get(current_frame), pxPoint.x, pxPoint.y, null); } else { Log.v("MapTest", "draw() : shadow = true"); } } @Override public void run() { Log.v("MapTest", "run()"); if (current_frame == mPngList.size() - 1) current_frame = 0; else current_frame++; mMapView.invalidate(); if (mStop == false) mHandler.postDelayed(this, sInterval); } public void resume() { mHandler.postDelayed(this, sInterval); mStop = false; } public void pause() { mStop = true; } }
以下は実行画面です。
これもまた、分かりにくいですが、画面中央付近の画像が変化(アニメーション)しています。