MapViewに付加できるいろいろな機能

前回地図の表示を作成しましたが、地図に付加できるいろいろな機能を紹介したいと思います。

まず、地図をつかんだりできるようにする為の関数

mapview.setEnabled(true);
mapview.setClickable(true);

次に拡大縮小を行う為のデフォルトのコントローラーは下記です。

mapview.setBuiltInZoomControls(true);

次にmapviewのコントローラーを作成します。(見えるものでなく、関数です。)

MapController mc=mapview.getController();

GPSで場所の指定ができます。

mc.setCenter(new GeoPoint(35609127,140113235));

またズームレベルの変更ができます。

mc.setZoom(16);

ともに値の取得に際しては、コントローラーの方ではなく、mapviewの方を利用します。

mapview.getMapCenter();
mapview.getZoomLevel();

以上で地図を作成するとほぼグーグルマップと同じ機能で地図を利用できると思います。しかし、次の機能がついてません。

・ダブルクリック
・長押し

この機能の追加に関してdispatchEventを利用する方法と、layerにイベントを追加する方法があります。

最終的にはlayerの方に追加をしたのですが、dispatchEventの方も不毛な勉強ではなかったので、ついでに記載をさせていただきます。

 

前提としては「MapViewではイベントを取得ができない」と言う問題がおこります。

OnDoubleTapListener,OnGestureListenerで取得をしたいのですが、どうやってもイベントがわたされません。

参照::Android: MapActivityでダブルタップする

dispatchEventを利用します。

 

dispatchEventは発行されるイベントを全て取得します。クリックも移動も全て取得をします。

なので、dispatchEventで取得したイベントはGestureDetectorを作成して、タッチイベントにイベントを渡す形で受け渡します。

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
 super.dispatchTouchEvent(ev);
 gestureDetector.onTouchEvent(ev);
 return onTouchEvent(ev);
}

このようにしてOnDoubleTapListener,OnGestureListenerをimplementsした関数に値を引き渡すとダブルクリックの動作も取得してくれます。

@Override
public boolean onDoubleTap(MotionEvent e) {
 return false;
}

@Override
public boolean onDoubleTapEvent(MotionEvent e) {
 return false;
}

のどちらかで実行をすればよいのだけど、このイベントの差って何だろうか。割と曖昧にしている片が多かったのですが、

参照::タッチパネルのダブルタップや長押しを検出する

onDoubleTapはダブルタップで、onDoubleTapEventはダブルタップ中のイベントらしいです。なぜか、onDoubleTapEventの中に動作を書こうとしている方が多かった印象なのですが、

@Override
public boolean onDoubleTap(MotionEvent e) {
 mc.zoomIn();
 return false;
}

などで、拡大ができる形がよいかと思います。

ソース一式

package in.andante.mapView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.View;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;

public class MapVVV extends MapActivity  implements OnGestureListener,OnDoubleTapListener, OnTouchListener{
 
 private GestureDetector gestureDetector;
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 MapView map = new MapView(this, "APIキー");
 
 map.setEnabled(true);
 map.setClickable(true);
 map.setBuiltInZoomControls(true);
 mc=map.getController();
 mc.setCenter(new GeoPoint(35609127,140113235));
 mc.setZoom(16);
 gestureDetector = new GestureDetector(this,this);
 setContentView(map);
 }
 MapController mc;
 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
 super.dispatchTouchEvent(ev);
 gestureDetector.onTouchEvent(ev);
 return onTouchEvent(ev);
 }
 
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 return false;
 }
 
 @Override
 protected boolean isRouteDisplayed() {
 return false;
 }
 
 @Override
 public void onLongPress(MotionEvent e) {
 }
 
 @Override
 public boolean onDoubleTap(MotionEvent e) {
 mc.zoomIn();
 return false;
 }

 @Override
 public boolean onDoubleTapEvent(MotionEvent e) {
 return false;
 }

 @Override
 public boolean onDown(MotionEvent arg0) {
 return false;
 }

 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
 return false;
 }

 @Override
 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
 return false;
 }

 @Override
 public void onShowPress(MotionEvent e) {
 }

 @Override
 public boolean onSingleTapUp(MotionEvent e) {
 return false;
 }

 @Override
 public boolean onSingleTapConfirmed(MotionEvent e) {
 return false;
 }
}

同様にしてonLongPress(長押し)の動作も設定ができるのですが、問題がひとつあって、zoomボタンの上などで、ダブルクリックをしても動作をしてしまいます

dispatchTouchEventが全てのイベントを取得してしまうが故にview上にさまざまな要素が増えれば増えただけ、修正が必要になります。

なので、次にレイヤーを利用して、ダブルクリックを取得してみましょう。

レイヤーとは、mapViewにはもともと上にレイヤーを重ねる事ができて、そこに矢印を配置したりできるのですが、そのレイヤーにイベントを持たせてあげるという方法です。

参照::特定のタップイベント時にMapViewから座標を取得する

レイヤーのクラスは下記の形になります。

class MyOverlay extends Overlay implements OnDoubleTapListener,OnGestureListener{
 
 private GestureDetector gesture = new GestureDetector(this);
 private MapView parent;

 MyOverlay(MapView mapView){
 parent = mapView;
 }
 
 @Override
 public boolean onTouchEvent(MotionEvent e, MapView mapView) {
 gesture.onTouchEvent(e);
 return super.onTouchEvent(e, mapView);
 }
 
 public void onLongPress(MotionEvent e) {

 }

 @Override
 public boolean onDown(MotionEvent e) {
 return false;
 }

 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
 return false;
 }

 @Override
 public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
 return false;
 }

 @Override
 public void onShowPress(MotionEvent e) {
 
 }

 @Override
 public boolean onSingleTapUp(MotionEvent e) {
 return false;
 }

 @Override
 public boolean onDoubleTap(MotionEvent e) {
 
 return false;
 }

 @Override
 public boolean onDoubleTapEvent(MotionEvent e) {
 mc.zoomIn();
 return false;
 }

 @Override
 public boolean onSingleTapConfirmed(MotionEvent e) {
 return false;
 }
 
}

上記のレイヤーをMapViewに追加をします。

map.getOverlays().add( new MyOverlay(map));

mapviewに重ねたレイヤー上にイベントを付加する事ができました。こちらの方法だと、今のところ、特に大きな問題もなく動作できると思います。

以上です。

  • written on 2011.04.25
  • category : map

前後の記事

前の記事:

次の記事:

関連の記事

コメントの投稿

  • サイト内検索

新作アプリの紹介

関連サイトの紹介

アンドロイドアプリ開発TIPS
きぐるみカメラ
ふらいぱん
アンドロイドのデザイン集
Page top↑