Free Hand Polygon on the Map in Google Map V2
を描きたいです。
このタスクはOverlay
Map V1で可能でしたが、Google MapはV2からそのクラスを削除しました。 (このあたり Google Map V2にはRemove Overlay Class )。
Google Map V1がフリースタイルのポリゴンを描画する良い例です
Map V2では、 Google Official Doc を使用してプログラムでポリゴンを描画できますが、ユーザーはどうすればよいですか? Map V2の不明な回答 が見つかりました
シンプルなGoogleマップから始めて、プログラムでこれを行うためにポリゴンを描画し、適切に機能していますが、今はユーザーがどのように描画できるかを探していますか?ポリゴンのマーカーに基づいて描画したくありません。
// Instantiates a new Polygon object and adds points to define a rectangle
PolygonOptions rectOptions = new PolygonOptions()
.add(new LatLng(37.35, -122.0),
new LatLng(37.45, -122.0),
new LatLng(37.45, -122.2),
new LatLng(37.35, -122.2),
new LatLng(37.35, -122.0));
// Get back the mutable Polygon
Polygon polygon = myMap.addPolygon(rectOptions);
私はこのトピックについて多くの研究開発を行ってきましたが、Map V2でそのようなことを実装するための完璧な方法は得られませんでした。
いくつかの質問
setOnDragListener
の画面座標に基づいて緯度経度を取得するにはどうすればよいですか?新しいバージョンには、古いバージョンに比べて何か特別なものがあるため、Map v2でも同じことを達成できると期待しています。
サンプルコードを提供したり、コードを投稿したりするのではなく、適切な指示とドキュメントを提供するだけです。
研究開発中に見つけたすべての文書と証拠を提供しました。
Rndで一日を過ごし、いくつかの選択肢をテストした後、解決策を見つけました。実際、同じ問題に対して2つの代替案を見つけましたが、代替案1と比較して非常に簡単なので、代替案2を使用することをお勧めします。
実際、私はAlternative 1を見つけました TheLittleNaruto 、 AndroidHacker およびその他の開発者&Alternative 2Khan の助けを借りて、すべてに感謝します。
代替1
Map V2でフリースタイルポリゴンを描画する方法(Map V1でできること) Map V2で実行可能ですか?
はい、それは実行可能ですが、マップ上でOnTouch()
&OnDraw()
を直接取得することはできません。そのため、これを達成するために他の方法を考えなければなりません。
この方法を達成するためのトリックや代替方法はありますか?
はい、Google Map V2は_class="com.google.Android.gms.maps.SupportMapFragment"
_を使用するマップでOnTouch()
またはOnDraw()
をサポートしていないため、カスタムフラグメントを計画する必要があります。
タッチイベントで緯度経度の配列を返すことは可能ですか?
はい。カスタムマップフラグメントを作成して使用すると、タッチまたはドラッグイベントをマップ上に取得できます。
SetOnDragListenerの画面座標に基づいてLat-longベースを取得するにはどうすればよいですか?
setOnDragListener
は、画面座標(x、y)を返します。そのため、(x、y)をLatLngに変換するいくつかの手法があり、それらには Projection と が含まれますPoint & LatLng 。
_customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() {@Override
public void onDrag(MotionEvent motionEvent) {
Log.i("ON_DRAG", "X:" + String.valueOf(motionEvent.getX()));
Log.i("ON_DRAG", "Y:" + String.valueOf(motionEvent.getY()));
float x = motionEvent.getX(); // get screen x position or coordinate
float y = motionEvent.getY(); // get screen y position or coordinate
int x_co = Integer.parseInt(String.valueOf(Math.round(x))); // casting float to int
int y_co = Integer.parseInt(String.valueOf(Math.round(y))); // casting float to int
projection = mMap.getProjection(); // Will convert your x,y to LatLng
Point x_y_points = new Point(x_co, y_co);// accept int x,y value
LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points); // convert x,y to LatLng
latitude = latLng.latitude; // your latitude
longitude = latLng.longitude; // your longitude
Log.i("ON_DRAG", "lat:" + latitude);
Log.i("ON_DRAG", "long:" + longitude);
// Handle motion event:
}
});
_
どのように機能しますか?
既に述べたように、カスタムルートビューを作成する必要がありますを使用して、マップ上でタッチまたはドラッグイベントを取得できます。
ステップ1:_MySupportMapFragment extends SupportMapFragment
_を作成し、それを.xmlファイルとして使用します
_ <fragment
Android:id="@+id/map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
class="pkg_name.MySupportMapFragment" />
_
ステップ2:_MapWrapperLayout extends FrameLayout
_を作成して、タッチまたはドラッグリスナーを内部に設定し、そのビューをマップビューに埋め込みます。そのため、Root_Map.Javaで使用する1つのインターフェイスが必要です
MySupportMapFragment.Java
_public class MySupportMapFragment extends SupportMapFragment {
public View mOriginalContentView;
public MapWrapperLayout mMapWrapperLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);
mMapWrapperLayout = new MapWrapperLayout(getActivity());
mMapWrapperLayout.addView(mOriginalContentView);
return mMapWrapperLayout;
}
@Override
public View getView() {
return mOriginalContentView;
}
public void setOnDragListener(MapWrapperLayout.OnDragListener onDragListener) {
mMapWrapperLayout.setOnDragListener(onDragListener);
}
}
_
MapWrapperLayout.Java
_ public class MapWrapperLayout extends FrameLayout {
private OnDragListener mOnDragListener;
public MapWrapperLayout(Context context) {
super(context);
}
public interface OnDragListener {
public void onDrag(MotionEvent motionEvent);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mOnDragListener != null) {
mOnDragListener.onDrag(ev);
}
return super.dispatchTouchEvent(ev);
}
public void setOnDragListener(OnDragListener mOnDragListener) {
this.mOnDragListener = mOnDragListener;
}
}
_
Root_Map.Java
_public class Root_Map extends FragmentActivity {
private GoogleMap mMap;
public static boolean mMapIsTouched = false;
MySupportMapFragment customMapFragment;
Projection projection;
public double latitude;
public double longitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.root_map);
MySupportMapFragment customMapFragment = ((MySupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
mMap = customMapFragment.getMap();
customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() { @Override
public void onDrag(MotionEvent motionEvent) {
Log.i("ON_DRAG", "X:" + String.valueOf(motionEvent.getX()));
Log.i("ON_DRAG", "Y:" + String.valueOf(motionEvent.getY()));
float x = motionEvent.getX();
float y = motionEvent.getY();
int x_co = Integer.parseInt(String.valueOf(Math.round(x)));
int y_co = Integer.parseInt(String.valueOf(Math.round(y)));
projection = mMap.getProjection();
Point x_y_points = new Point(x_co, y_co);
LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points);
latitude = latLng.latitude;
longitude = latLng.longitude;
Log.i("ON_DRAG", "lat:" + latitude);
Log.i("ON_DRAG", "long:" + longitude);
// Handle motion event:
}
});
}}
_
ここまでで、LatLongをX、Yスクリーン座標に基づいて取得できます。ここで、Arrayに保存するだけです。その配列は、マップ上での描画に使用され、最終的には自由形状のポリゴンのようになります。
これがあなたのお役に立てば幸いです。
代替案2
ご存知のように、フレームレイアウトは透過レイアウトなので、フレームレイアウトを使用してこれを実現しました。この場合、カスタムフラグメントを作成する必要はありません。ルートレイアウトとしてフレームレイアウトを使用しました。したがって、基本的にルートレイアウトでTouch Eventsを取得し、以前にカスタムフラグメントで取得したように、画面座標を返します。
これで、「フリードロー」内にボタンを作成しました。そのため、それをクリックすると、地図上で指を動かしてフリーハンドのポリゴンを描くことができ、画面上で地図が移動できなくなります。同じボタンを再度クリックすると、画面は理想的なモードになります。
root_map.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" >
<fragment
Android:id="@+id/map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
class="com.google.Android.gms.maps.SupportMapFragment" />
<FrameLayout
Android:id="@+id/fram_map"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent" >
<Button
Android:id="@+id/btn_draw_State"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Free Draw" />
</FrameLayout>
</FrameLayout>
_
Root_Map.Java
_FrameLayout fram_map = (FrameLayout) findViewById(R.id.fram_map);
Button btn_draw_State = (Button) findViewById(R.id.btn_draw_State);
Boolean Is_MAP_Moveable = false; // to detect map is movable
_
//ボタンはマップの可動状態を変更します
_btn_draw_State.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Is_MAP_Moveable = !Is_MAP_Moveable;
}
});
_
[フレームレイアウト]の[クリック]をタッチし、タスクを実行します
_fram_map.setOnTouchListener(new View.OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
int x_co = Math.round(x);
int y_co = Math.round(y);
projection = mMap.getProjection();
Point x_y_points = new Point(x_co, y_co);
LatLng latLng = mMap.getProjection().fromScreenLocation(x_y_points);
latitude = latLng.latitude;
longitude = latLng.longitude;
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
// finger touches the screen
val.add(new LatLng(latitude, longitude));
case MotionEvent.ACTION_MOVE:
// finger moves on the screen
val.add(new LatLng(latitude, longitude));
case MotionEvent.ACTION_UP:
// finger leaves the screen
Draw_Map();
break;
}
return Is_MAP_Moveable;
}
});
_
//マップを描画します
_public void Draw_Map() {
rectOptions = new PolygonOptions();
rectOptions.addAll(val);
rectOptions.strokeColor(Color.BLUE);
rectOptions.strokeWidth(7);
rectOptions.fillColor(Color.CYAN);
polygon = mMap.addPolygon(rectOptions);
}
_
ただし、描画中はリストを維持する必要があるため、以前のリストデータを消去する必要があります。
これをチェックしてください.. UはGoogle Map v2を表示できると思います
AsyncTaskの「decodePoly」および「drawPath」メソッドを確認してください
「drawPath」の主な特徴..
PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
for (int z = 0; z < list.size(); z++) {
LatLng point = list.get(z);
options.add(point);
}
line = myMap.addPolyline(options);
参考のための完全なクラス..
package com.example.androidhackergooglemap;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.InputStreamReader;
import Java.io.UnsupportedEncodingException;
import Java.util.ArrayList;
import Java.util.List;
import org.Apache.http.HttpEntity;
import org.Apache.http.HttpResponse;
import org.Apache.http.client.ClientProtocolException;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import com.google.Android.gms.maps.CameraUpdateFactory;
import com.google.Android.gms.maps.GoogleMap;
import com.google.Android.gms.maps.SupportMapFragment;
import com.google.Android.gms.maps.model.BitmapDescriptorFactory;
import com.google.Android.gms.maps.model.LatLng;
import com.google.Android.gms.maps.model.Marker;
import com.google.Android.gms.maps.model.MarkerOptions;
import com.google.Android.gms.maps.model.Polyline;
import com.google.Android.gms.maps.model.PolylineOptions;
import Android.app.ProgressDialog;
import Android.content.Context;
import Android.content.Intent;
import Android.graphics.Color;
import Android.location.Location;
import Android.location.LocationManager;
import Android.os.AsyncTask;
import Android.os.Bundle;
import Android.provider.Settings;
import Android.support.v4.app.FragmentActivity;
import Android.util.Log;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.Toast;
public class MainActivity extends FragmentActivity implements OnClickListener {
private GoogleMap myMap;
Polyline line;
Context context;
Location location;
boolean check_provider_enabled = false;
// Static LatLng
LatLng startLatLng = new LatLng(30.707104, 76.690749);
LatLng endLatLng = new LatLng(30.721419, 76.730017);
public void onCreate(Bundle bd) {
super.onCreate(bd);
setContentView(R.layout.activity_main);
context = MainActivity.this;
// GoogleMap myMap
myMap = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
myMap.setMyLocationEnabled(true);
myMap.moveCamera(CameraUpdateFactory.newLatLng(startLatLng));
myMap.animateCamera(CameraUpdateFactory.zoomTo(12));
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
location = service.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// check if enabled and if not send user to the GSP settings
// Better solution would be to display a dialog and suggesting to
// go to the settings
if (!enabled) {
/*Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);*/
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Toast.makeText(getApplicationContext(), "Enable GPS servcies to use this app.", Toast.LENGTH_LONG).show();
} else {
try {
String urlTopass = makeURL(startLatLng.latitude,
startLatLng.longitude, endLatLng.latitude,
endLatLng.longitude);
new connectAsyncTask(urlTopass).execute();
} catch (Exception e) {
e.printStackTrace();
}
}
// Now auto clicking the button
// btntemp.performClick();
}
private class connectAsyncTask extends AsyncTask < Void, Void, String > {
private ProgressDialog progressDialog;
String url;
connectAsyncTask(String urlPass) {
url = urlPass;
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Fetching route, Please wait...");
progressDialog.setIndeterminate(true);
progressDialog.show();
}
@Override
protected String doInBackground(Void...params) {
JSONParser jParser = new JSONParser();
String json = jParser.getJSONFromUrl(url);
return json;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progressDialog.hide();
if (result != null) {
drawPath(result);
}
}
}
public String makeURL(double sourcelat, double sourcelog, double destlat,
double destlog) {
StringBuilder urlString = new StringBuilder();
urlString.append("http://maps.googleapis.com/maps/api/directions/json");
urlString.append("?origin="); // from
urlString.append(Double.toString(sourcelat));
urlString.append(",");
urlString.append(Double.toString(sourcelog));
urlString.append("&destination="); // to
urlString.append(Double.toString(destlat));
urlString.append(",");
urlString.append(Double.toString(destlog));
urlString.append("&sensor=false&mode=driving&alternatives=true");
return urlString.toString();
}
public class JSONParser {
InputStream is = null;
JSONObject jObj = null;
String json = "";
// constructor
public JSONParser() {}
public String getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
json = sb.toString();
is.close();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
return json;
}
}
public void drawPath(String result) {
if (line != null) {
myMap.clear();
}
myMap.addMarker(new MarkerOptions().position(endLatLng).icon(
BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
myMap.addMarker(new MarkerOptions().position(startLatLng).icon(
BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));
try {
// Tranform the string into a json object
final JSONObject json = new JSONObject(result);
JSONArray routeArray = json.getJSONArray("routes");
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes
.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
List < LatLng > list = decodePoly(encodedString);
PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
for (int z = 0; z < list.size(); z++) {
LatLng point = list.get(z);
options.add(point);
}
line = myMap.addPolyline(options);
/*for (int z = 0; z < list.size() - 1; z++) {
LatLng src = list.get(z);
LatLng dest = list.get(z + 1);
line = myMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
.width(5).color(Color.BLUE).geodesic(true));
}*/
} catch (Exception e) {
e.printStackTrace();
}
}
private List < LatLng > decodePoly(String encoded) {
List < LatLng > poly = new ArrayList < LatLng > ();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
}
それが役に立てば幸い。乾杯!
[〜#〜] update [〜#〜]
これを確認してください.. Google Map v2フラグメント用のOnDragListenerの作成
また、これをチェックしてください.. GoogleマップV2を使用してタッチすることでマップフラグメントに図形を描画する方法
いくつかの参照.. Googleマップv2 Androidのマーカーから画面座標を取得する方法
そのため、マップv2にフリーハンドで描画するためのソリューションがあります。実装GoogleMap.OnMarkerDragListener
マップアクティビティ内。 onMarkerDrag関数をオーバーライドします。
@Override
public void onMarkerDrag(Marker marker) {
//add the marker's latlng in a arraylist of LatLng and pass it to the loop
for (int i = 0; i < arraylistoflatlng.size(); i++) {
myMap.addPolyline(new PolylineOptions()
.addAll(arraylistoflatlng)
.width(5)
.color(Color.RED));
}
}
ユーザーが地図に触れるとすぐに、ある種のハックをフリーハンドで渡すことができます。その座標を検出してonMarkerDragに渡す必要があります。今後のプロセスのためにエリアの情報を使用する必要があります。タッチイベントの場合は、GoogleMap.OnMapClickListener
そして、そのパラメーターから座標を取得します。これが役立つことを願っています:)
これはgoogle maps API V2チュートリアルです:
public class MapPane extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map_activity);
GoogleMap map = ((MapFragment) getFragmentManager()
.findFragmentById(R.id.map)).getMap();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(-18.142, 178.431), 2));
// Polylines are useful for marking paths and routes on the map.
map.addPolyline(new PolylineOptions().geodesic(true)
.add(new LatLng(-33.866, 151.195)) // Sydney
.add(new LatLng(-18.142, 178.431)) // Fiji
.add(new LatLng(21.291, -157.821)) // Hawaii
.add(new LatLng(37.423, -122.091)) // Mountain View
);
}
}
リンク: https://developers.google.com/maps/documentation/Android/