地図上には飲食店や建築物といったランドマークが存在します。
SkobblerではPOIと呼びます。
POIは「Skobblerが用意したPOI-SKMapPOI」、「ユーザーが作るPOI-SKMapCustomPOI」の2種類存在します。
POIが同じ緯度経度に存在するときは一つの「SKPOICluster」にまとめられます。
また、地図上に配置されたPOIはSKMapSurfaceListenerでイベントを取得することができます。
SKMapSurfaceListener#onMapPOISelected | SKMapPOIがタップされたときに呼ばれる。 |
SKMapSurfaceListener#onPOIClusterSelected | SKPOIClusterがタップされたときに呼ばれる。 |
SKMapSurfaceListener#onCustomPOISelected | SKMapCustomPOIがタップされたときに呼ばれる。 |
SKMapSurfaceViewにはPOIを操作するメソッドが存在します。
addCustomPOI | SKMapCustomPOIを地図に配置する。 |
addCustomPOIs | SKMapCustomPOIのリストを地図に配置する。 |
getAllCustomPOIS | 地図上のSKMapCustomPOIをすべて取得する。 |
deleteCustomPOI | SKMapCustomPOIを削除する。 |
deleteAllAnnotationsAndCustomPOIs | 地図上のSKMapCustomPOIをすべて削除する |
showHeatMapsWithPoiType | 指定したタイプのPOIのヒートマップを表示する。 |
clearHeatMapsDisplay | ヒートマップを削除する。 |
public class MainActivity extends AppCompatActivity implements SKPrepareMapTextureListener, SKMapSurfaceListener {
private SKMapSurfaceView mapView;
private SKMapViewHolder mapHolder;
String mapResourcesDirPath;
private SKCoordinate tokyo = new SKCoordinate(139.766084, 35.681382);
private SKBoundingBox limitSkBoundingBox = new SKBoundingBox(
tokyo.getLatitude() + 0.1,
tokyo.getLongitude() - 0.1,
tokyo.getLatitude() - 0.1,
tokyo.getLongitude() + 0.1
);
private SKCoordinateRegion lastValidRegion;
@Override
public void onSingleTap(SKScreenPoint skScreenPoint) {
//タップ(ActionDown-ActionUp)したときに呼ばれる。
Log.d("SKMapSurfaceListener", "onSingleTap");
Log.d("SKMapSurfaceListener", "onSingleTap[x:" + skScreenPoint.getX() + "/y:" + skScreenPoint.getY() + "]");
// SKAnnotation skAnnotation = createSKAnnotation(
// mapView.getAllAnnotations().size(),
// SKAnnotation.SK_ANNOTATION_TYPE_MARKER,
// 0,
// skScreenPoint, null);
// SKAnimationSettings skAnimationSettings = new SKAnimationSettings(
// SKAnimationSettings.SKAnimationType.PULSE_CCP,
// SKAnimationSettings.SKEasingType.EASE_IN_EXPO,
// 1000
// );
// mapView.addAnnotation(skAnnotation, skAnimationSettings);
mapView.addCustomPOI(createSKMapCustomPOI(
mapView.getAllCustomPOIS().size(),
mapView.pointToCoordinate(skScreenPoint),
SKCategories.SKPOICategory.SKPOI_CATEGORY_AIRPORT,
null
));
}
private SKMapCustomPOI createSKMapCustomPOI(int id, SKCoordinate skCoordinate, SKCategories.SKPOICategory category, SKMapCustomPOI.SKPoiType type) {
SKMapCustomPOI skMapCustomPOI = new SKMapCustomPOI();
//ID
skMapCustomPOI.setUniqueID(id);
//位置を設定
skMapCustomPOI.setLocation(skCoordinate);
//カテゴリを設定
skMapCustomPOI.setCategory(category);
//タイプを設定する
skMapCustomPOI.setPoiType(type);
return skMapCustomPOI;
}
@Override
public void onMapPOISelected(SKMapPOI skMapPOI) {
Log.d("SKMapSurfaceListener", "onMapPOISelected");
Log.d("SKMapSurfaceListener", "name:" + skMapPOI.getName());
Log.d("SKMapSurfaceListener", "Category name:" + skMapPOI.getCategory().name());
Log.d("SKMapSurfaceListener", "Lat:" + skMapPOI.getLocation().getLatitude());
Log.d("SKMapSurfaceListener", "Log:" + skMapPOI.getLocation().getLongitude());
List<sksearchresultparent> skSearchResultParents = skMapPOI.getParentsList();
for (SKSearchResultParent skSearchResultParent : skSearchResultParents) {
Log.d("SKMapSurfaceListener", "SKSearchResultParent Parent Name:" + skSearchResultParent.getParentName());
Log.d("SKMapSurfaceListener", "SKSearchResultParent Parent Type:" + skSearchResultParent.getParentType());
}
}
@Override
public void onPOIClusterSelected(SKPOICluster skpoiCluster) {
Log.d("SKMapSurfaceListener", "onPOIClusterSelected");
List<skmappoi> skMapPOIs = skpoiCluster.getMapPOIsList();
for (SKMapPOI skMapPOI : skMapPOIs) {
Log.d("SKMapSurfaceListener", "name:" + skMapPOI.getName());
Log.d("SKMapSurfaceListener", "Category name:" + skMapPOI.getCategory().name());
Log.d("SKMapSurfaceListener", "Lat:" + skMapPOI.getLocation().getLatitude());
Log.d("SKMapSurfaceListener", "Log:" + skMapPOI.getLocation().getLongitude());
List<sksearchresultparent> skSearchResultParents = skMapPOI.getParentsList();
for (SKSearchResultParent skSearchResultParent : skSearchResultParents) {
Log.d("SKMapSurfaceListener", "SKSearchResultParent Parent Name:" + skSearchResultParent.getParentName());
Log.d("SKMapSurfaceListener", "SKSearchResultParent Parent Type:" + skSearchResultParent.getParentType());
}
}
}
@Override
public void onCustomPOISelected(SKMapCustomPOI skMapCustomPOI) {
Log.d("SKMapSurfaceListener", "onCustomPOISelected");
Log.d("SKMapSurfaceListener", "id:" + skMapCustomPOI.getUniqueID());
Log.d("SKMapSurfaceListener", "Category name:" + skMapCustomPOI.getCategory().name());
Log.d("SKMapSurfaceListener", "Lat:" + skMapCustomPOI.getLocation().getLatitude());
Log.d("SKMapSurfaceListener", "Log:" + skMapCustomPOI.getLocation().getLongitude());
}
@Override
public void onInternetConnectionNeeded() {
}
@Override
public void onCompassSelected() {
}
@Override
public void onCurrentPositionSelected() {
}
@Override
public void onObjectSelected(int i) {
}
@Override
public void onInternationalisationCalled(int i) {
}
@Override
public void onBoundingBoxImageRendered(int i) {
}
@Override
public void onGLInitializationError(String s) {
}
@Override
public void onScreenshotReady(Bitmap bitmap) {
}
@Override
public void onMapRegionChangeStarted(SKCoordinateRegion skCoordinateRegion) {
//SKCoordinateRegionの変化開始で呼ばれる
Log.d("SKMapSurfaceListener", "onMapRegionChangeStarted");
Log.d("SKMapSurfaceListener", "SKBoundingBox:[Latitude-" + skCoordinateRegion.getCenter().getLatitude() + "/Longitude-" + skCoordinateRegion.getCenter().getLongitude() + "]");
}
@Override
public void onMapRegionChanged(SKCoordinateRegion skCoordinateRegion) {
//SKCoordinateRegionの変化で呼ばれる
Log.d("SKMapSurfaceListener", "onMapRegionChanged");
Log.d("SKMapSurfaceListener", "SKBoundingBox:[Latitude-" + skCoordinateRegion.getCenter().getLatitude() + "/Longitude-" + skCoordinateRegion.getCenter().getLongitude() + "]");
if (isInBoundingBox(skCoordinateRegion)) {
if (lastValidRegion == null) {
lastValidRegion = new SKCoordinateRegion(skCoordinateRegion.getCenter(), skCoordinateRegion.getZoomLevel());
} else {
lastValidRegion.setCenter(skCoordinateRegion.getCenter());
lastValidRegion.setZoomLevel(skCoordinateRegion.getZoomLevel());
}
} else {
if (lastValidRegion != null) {
//指定したRegionに移動する。
mapView.changeMapVisibleRegion(lastValidRegion, false);
}
}
}
@Override
public void onMapRegionChangeEnded(SKCoordinateRegion skCoordinateRegion) {
//SKCoordinateRegionの変化終了で呼ばれる
Log.d("SKMapSurfaceListener", "onMapRegionChangeEnded");
Log.d("SKMapSurfaceListener", "SKBoundingBox:[Latitude-" + skCoordinateRegion.getCenter().getLatitude() + "/Longitude-" + skCoordinateRegion.getCenter().getLongitude() + "]");
}
@Override
public void onAnnotationSelected(SKAnnotation skAnnotation) {
Log.d("SKMapSurfaceListener", "onAnnotationSelected");
Log.d("SKMapSurfaceListener", "onAnnotationSelected[x:" + skAnnotation.getUniqueID() + "]");
// changeAnnotations(skAnnotation);
}
@Override
public void onMapActionDown(SKScreenPoint skScreenPoint) {
//マップに指が触れたときに呼ばれる。
Log.d("SKMapSurfaceListener", "onMapActionDown");
Log.d("SKMapSurfaceListener", "onMapActionDown[x:" + skScreenPoint.getX() + "/y:" + skScreenPoint.getY() + "]");
}
@Override
public void onDoubleTap(SKScreenPoint skScreenPoint) {
//ダブルタップ(ActionDown-ActionUp-ActionDown-ActionUp)したときに呼ばれる。
Log.d("SKMapSurfaceListener", "onDoubleTap");
Log.d("SKMapSurfaceListener", "onDoubleTap[x:" + skScreenPoint.getX() + "/y:" + skScreenPoint.getY() + "]");
ImageView imageView = new ImageView(getApplicationContext());
imageView.setImageResource(R.mipmap.ic_launcher);
SKAnnotation skAnnotation = createSKAnnotation(
mapView.getAllAnnotations().size(),
SKAnnotation.SK_ANNOTATION_TYPE_MARKER,
0,
skScreenPoint, imageView);
SKAnimationSettings skAnimationSettings = new SKAnimationSettings(
SKAnimationSettings.SKAnimationType.PIN_DROP,
SKAnimationSettings.SKEasingType.EASE_IN_EXPO,
1000
);
mapView.addAnnotation(skAnnotation, skAnimationSettings);
}
@Override
public void onSurfaceCreated(SKMapViewHolder skMapViewHolder) {
mapHolder = skMapViewHolder;
mapView = skMapViewHolder.getMapSurfaceView();
mapView.centerMapOnPosition(new SKCoordinate(139.766084, 35.681382));
// initMapSettings();
// settingScaleView();
}
@Override
public void onLongPress(SKScreenPoint skScreenPoint) {
//長押ししたときに呼ばれる。
Log.d("SKMapSurfaceListener", "onLongPress");
Log.d("SKMapSurfaceListener", "onLongPress[x:" + skScreenPoint.getX() + "/y:" + skScreenPoint.getY() + "]");
}
@Override
public void onActionPan() {
//移動したときに呼ばれる。
Log.d("SKMapSurfaceListener", "onActionPan");
}
@Override
public void onActionZoom() {
//ズームしたときに呼ばれる。
Log.d("SKMapSurfaceListener", "onActionZoom");
}
@Override
public void onRotateMap() {
//回転したときに呼ばれる。
Log.d("SKMapSurfaceListener", "onRotateMap");
}
@Override
public void onMapActionUp(SKScreenPoint skScreenPoint) {
//マップから指から離れたときに呼ばれる。
Log.d("SKMapSurfaceListener", "onMapActionUp");
Log.d("SKMapSurfaceListener", "onMapActionUp[x:" + skScreenPoint.getX() + "/y:" + skScreenPoint.getY() + "]");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapResourcesDirPath = getFilesDir().getPath() + "/" + "SKMaps/";
if (!new File(mapResourcesDirPath).exists()) {
new SKPrepareMapTextureThread(this, mapResourcesDirPath, "SKMaps.zip", this).start();
} else {
initMapSetting();
}
}
@Override
public void onMapTexturesPrepared(boolean b) {
if (b) {
initMapSetting();
}
}
private void initMapSetting() {
SKMapsInitSettings initMapSettings = new SKMapsInitSettings();
initMapSettings.setMapResourcesPaths(mapResourcesDirPath,
new SKMapViewStyle(mapResourcesDirPath + "daystyle/", "daystyle.json"));
final SKAdvisorSettings advisorSettings = initMapSettings.getAdvisorSettings();
advisorSettings.setAdvisorConfigPath(mapResourcesDirPath + "Advisor");
advisorSettings.setResourcePath(mapResourcesDirPath + "Advisor/Languages");
advisorSettings.setLanguage(SKAdvisorSettings.SKAdvisorLanguage.LANGUAGE_EN);
advisorSettings.setAdvisorVoice("en");
initMapSettings.setAdvisorSettings(advisorSettings);
SKMaps.getInstance().initializeSKMaps(this, initMapSettings);
SKMapFragment mapFragment = new SKMapFragment();
mapFragment.setMapSurfaceListener(this);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.container, mapFragment).commit();
}
@Override
protected void onPause() {
super.onPause();
if (mapHolder != null) {
mapHolder.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mapHolder != null) {
mapHolder.onResume();
}
}
private void initMapSettings() {
//地図描画フレームレートの最大値を設定する。ただし、ユーザー操作は含まれない。
mapView.getMapSettings().setFrameRate(60);
//地図の表示領域が何を追尾モードを指定する。
//例えば下記のようにするとユーザーの位置が地図の中心に来るように追尾します。
mapView.getMapSettings().setFollowerMode(SKMapSettings.SKMapFollowerMode.NONE);
//地図の言語設定に使用する。
SKMapInternationalizationSettings skMapInternationalizationSettings = new SKMapInternationalizationSettings();
skMapInternationalizationSettings.setPrimaryLanguage(SKMaps.SKLanguage.LANGUAGE_RU);
mapView.getMapSettings().setMapInternationalizationSettings(skMapInternationalizationSettings);
settingsUserAction();
settingsMapObject();
settingsPoi();
settingsStyle();
settings3D();
//以下は使い方がわからない調査中メソッド
//mapView.getMapSettings().setDrawingOrder();
//mapView.getMapSettings().setTerrainEnabled(false);
//mapView.getMapSettings().setTerrainDisabledIfNoElevation(false);
//mapView.getMapSettings().setOrientationIndicatorType();
//mapView.getMapSettings().setGeneratedPoisShown(false);
//mapView.getMapSettings().setImportantPoisShown(true);
}
private void settings3D() {
//地図を3D表示したときのカメラを設定する。
SK3DCameraSettings sk3DCameraSettings = new SK3DCameraSettings();
sk3DCameraSettings.setTilt(60);
sk3DCameraSettings.setCenter(0.9f);
sk3DCameraSettings.setDistance(10);
mapView.getMapSettings().setCameraSettings(sk3DCameraSettings);
//地図を拡大した表示を2Dと3Dのどちらかを指定することができます。
mapView.getMapSettings().setMapDisplayMode(SKMapSettings.SKMapDisplayMode.MODE_3D);
//通りの名前をポップアップ風に表示する。true:ポップアップ表示/false:地図上に書き込み
mapView.getMapSettings().setStreetNamePopupsShown(false);
}
private void settingsStyle() {
// 地図を描画する時に使うスタイルファイルを設定する。
//SKMaps.zip内にはデフォルトで下記の4styleが存在します。
String daystyle = "daystyle";
String grayscalestyle = "grayscalestyle";
String nightstyle = "nightstyle";
String outdoorstyle = "outdoorstyle";
String style = nightstyle;
//コンストラクタの引数はstyleファイルが存在するフォルダとstyleファイルの名前です。
SKMapViewStyle skMapViewStyle = new SKMapViewStyle(mapResourcesDirPath + style + "/", style + ".json");
mapView.getMapSettings().setMapStyle(skMapViewStyle);
}
private void settingsPoi() {
//POIはランドマークのことです。
//POIの表示非表示を設定する true:表示/false:非表示
mapView.getMapSettings().setMapPoiIconsShown(true);
//地図上の都市情報の表示非表示を設定する true:表示/false:非表示
//country:国名/state:州名/city:都市名/town:街名/village:村名などなど
mapView.getMapSettings().setCityPoisShown(true);
}
private void settingsMapObject() {
//自転車専用レーンの表示非表示を設定する true:表示/false:非表示
mapView.getMapSettings().setShowBicycleLanes(true);
//一方通行の表示非表示を設定する true:表示/false:非表示
mapView.getMapSettings().setOneWayArrows(true);
//同一建物内の店舗数の表示非表示を設定する true:表示/false:非表示
mapView.getMapSettings().setHouseNumbersShown(true);
//自分の位置の表示非表示を設定する。true:表示/false:非表示
//初期表示位置はなぜか北極点
mapView.getMapSettings().setCurrentPositionShown(false);
//コンパスの表示-true:表示/false:非表示
mapView.getMapSettings().setCompassShown(true);
//コンパスの位置を指定する。右上を原点とする。
mapView.getMapSettings().setCompassPosition(new SKScreenPoint(10, 10));
}
private void settingsUserAction() {
//地図の移動の有効無効を設定する。true:有効/false:無効
mapView.getMapSettings().setMapPanningEnabled(false);
//地図の回転の有効無効を設定する true:有効/false:無効
mapView.getMapSettings().setMapRotationEnabled(false);
//Zoomの有効無効を設定する。true:有効/false:無効
mapView.getMapSettings().setMapZoomingEnabled(true);
//地図の移動に慣性力を付加する。 true:有効/false:無効
mapView.getMapSettings().setInertiaPanningEnabled(false);
//地図の回転に慣性力を付加する。 true:有効/false:無効
mapView.getMapSettings().setInertiaRotatingEnabled(false);
//地図のズームに慣性力を付加する。 true:有効/false:無効
mapView.getMapSettings().setInertiaZoomingEnabled(false);
//アンカーポイントを中心にZoomをするかを設定する。
// true:アンカー(地図中心)にZoomする。/false:ピンチしている指の間を中心にZoomする。
mapView.getMapSettings().setZoomWithAnchorEnabled(false);
//Zoomの上下限を設定するメソッド
//しかし、どんな値を設定しても特に変化がない。
mapView.getMapSettings().setZoomLimits(5f, 19f);
//リファレンスに説明が無く、値を変更しても反応しない。
//動作しないメソッドなのか?
mapView.getMapSettings().setMinimumZoomForTapping(0);
}
private void settingScaleView() {
//縮尺の表示を有効にする。
mapHolder.setScaleViewEnabled(true);
//縮尺を右下に配置する。
mapHolder.setScaleViewPosition(0, 80, RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.ALIGN_PARENT_BOTTOM);
//SKMapScaleViewのインスタンスを取得する。
SKMapScaleView scaleView = mapHolder.getScaleView();
//枠線の色を指定する。
scaleView.setBorderColor(Color.RED);
//SKMapScaleViewのバーは明るい色と黒い色の二色で塗り分けられます。
//暗い色を指定します。
scaleView.setDarkerColor(Color.BLUE);
//明るい色を指定します。
scaleView.setLighterColor(Color.GREEN);
//テキストの色を指定します。
scaleView.setTextColor(Color.CYAN);
//縮尺の単位を指定します。キロメーター、マイルフィート、マイルヤードから選択できます。
scaleView.setDistanceUnit(SKMaps.SKDistanceUnitType.DISTANCE_UNIT_KILOMETER_METERS);
//各単位のラベルを指定する。
scaleView.setDistanceUnitLabels("kmのラベル", "mのラベル", "miのラベル", "ftのラベル", "ydのラベル");
//SKMapScaleViewの自動フェイドアウトアニメーションの有効無効を設定する。true:フェイドアウトする/false:フェイドアウトしない
scaleView.setFadeOutEnabled(false);
}
private void changeAnnotations(SKAnnotation skAnnotation) {
//地図上に存在するアノテーションのリストを取得する。
List<skannotation> skAnnotationList = mapView.getAllAnnotations();
if (skAnnotationList.size() > 5) {
//地図上のすべてのアノテーションおよびカスタムPOIを削除します。
mapView.deleteAllAnnotationsAndCustomPOIs();
}
if (skAnnotationList.size() % 2 == 0) {
//タップされたアノテーションを最前面にする。
mapView.bringToFrontAnnotationWithID(skAnnotation.getUniqueID());
//タップされたアノテーションのタイプを更新する。
skAnnotation.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_BLUE);
mapView.updateAnnotation(skAnnotation);
} else {
//タップされたアノテーションを削除する。
mapView.deleteAnnotation(skAnnotation.getUniqueID());
}
}
/**
* アノテーションを作成する。
*
* @param uniqueID ID
* @param type 見た目
* @param minimum ????
* @param location 画面座標位置
* @param pinView 独自VIew
* @return
*/
private SKAnnotation createSKAnnotation(int uniqueID, int type, int minimum, SKScreenPoint location, View pinView) {
//SKAnnotationインスタンスを作成、引数はID
SKAnnotation skAnnotation = new SKAnnotation(uniqueID);
//IDの変更
skAnnotation.setAnnotationType(uniqueID);
//SKAnnotationの位置指定は緯度経度が必要です。
//しかし、SKScreenPointは画面上の位置なので緯度経度に変換する必要があります。
//SKMapSurfaceView#pointToCoordinateを使うことで変換ができます。
SKCoordinate skCoordinate = mapView.pointToCoordinate(location);
//SKAnnotationの位置を指定する。
skAnnotation.setLocation(skCoordinate);
//ピンの見た目はデフォルトで用意されているアイコン
//または独自Viewのどちらかをセットできます。
//どちらもセットされないと何も表示されません。
//SKAnnotation.SK_ANNOTATION_TYPE_BLUE
//SKAnnotation.SK_ANNOTATION_TYPE_DESTINATION_FLAG
//SKAnnotation.SK_ANNOTATION_TYPE_GREEN
//SKAnnotation.SK_ANNOTATION_TYPE_MARKER
//SKAnnotation.SK_ANNOTATION_TYPE_PURPLE
//SKAnnotation.SK_ANNOTATION_TYPE_RED
//デフォルトのピンをセットする。
if (pinView == null) {
skAnnotation.setAnnotationType(type);
} else {
//独自Viewを配置する場合はSKAnnotationViewを使う。
SKAnnotationView skAnnotationView = new SKAnnotationView();
//Viewをセットする。
skAnnotationView.setView(pinView);
//SKAnnotationViewをセットする。
skAnnotation.setAnnotationView(skAnnotationView);
}
//ピンが表示される最小ズームレベルを指定する。
//いろいろな値を指定しても変わらない。動かない?
//第一メソッド名がminimumではないのは何故
skAnnotation.setMininumZoomLevel(minimum);
//何のオフセットしているのかわからない
SKScreenPoint skScreenPoint = new SKScreenPoint();
skScreenPoint.setX(5);
skScreenPoint.setY(5);
skAnnotation.setOffset(skScreenPoint);
return skAnnotation;
}
// checks if a given region is inside the bounding box
private boolean isInBoundingBox(SKCoordinateRegion newRegion) {
//SKCoordinateRegionを現在表示している左上と右下端緯度経度を持つSKBoundingBoxに変換する。
SKBoundingBox newBoundingBox = mapView.getBoundingBoxForRegion(newRegion);
if (newBoundingBox.getTopLeftLatitude() > limitSkBoundingBox.getTopLeftLatitude()
|| newBoundingBox.getBottomRightLatitude() < limitSkBoundingBox.getBottomRightLatitude()
|| newBoundingBox.getTopLeftLongitude() < limitSkBoundingBox.getTopLeftLongitude()
|| newBoundingBox.getBottomRightLongitude() > limitSkBoundingBox.getBottomRightLongitude()) {
return false;
}
return true;
}
}