我想画一个Free Hand Polygon on the Map in Google Map V2
。
使用Overlay
Map V1可以执行此任务,但Google已将该类从V2中删除。(按此Google V2已删除覆盖类)。
在Map V2中,我们可以在谷歌官方文件的帮助下以编程方式绘制多边形,但是用户应该做什么呢?我找到了地图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
上的屏幕坐标获得Lat-long?与以前的版本相比,每个新版本都有一些额外的功能,所以我希望我也能在Map v2中实现同样的目标。
我不是要求给我一些示例代码或发布您的代码,只是一些正确的指导和文档。
我提供了我在研发过程中发现的所有文件和证据。
发布于 2014-01-04 04:34:56
在Rnd花了一整天时间测试了一些替代方案之后,我找到了一个解决方案。实际上,我已经为同一问题找到了两个替代方案,但我想建议使用Alternative 2,因为与Alternative 1相比,这非常容易。
实际上,在、AndroidHacker和其他一些开发人员的帮助下,我找到了TheLittleNaruto Alternative 1& Alternative 2和可汗的帮助,所以感谢所有这些。
备选方案1
如何在Map V2中绘制自由样式多边形(就像我们可以用Map V1绘制的那样)?它在地图V2中可行吗?
是的,这是可行的,但是你不能直接得到地图上的OnTouch()
& OnDraw()
。因此,我们必须想出其他方法来实现这一目标。
如果是的话,有什么办法或替代方法来达到这个目的吗?
是的,Google V2不支持OnTouch()
或OnDraw()
在地图上使用class="com.google.android.gms.maps.SupportMapFragment"
,所以我们必须为定制片段进行规划。
有可能用触摸事件返回lat-long数组吗?
是的,如果我们创建任何定制的映射片段并使用它,我们就可以获得Touch或将事件拖到地图上。
如何在setOnDragListener上获得屏幕坐标上的Lat-long基?
setOnDragListener
将返回屏幕坐标(x,y)。现在,有一些技术可以将(x,y)转换为LatLng,其中包括投影和点 & 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:
}
});
它是怎么工作的?
正如我前面提到的,我们必须创建一个自定义根视图,并使用它我们可以在地图上获得Touch或拖动事件。
步骤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中使用的接口
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:
}
});
}}
到目前为止,我能够得到基于X,Y屏幕坐标的LatLong。现在,我只需将其存储在数组中。该数组将用于在地图上绘制,最后它将看起来像一个自由形状的多边形。
我希望这肯定会对你有帮助。
更新:
备选方案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
// Button将更改Map可移动状态
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);
}
然而,现在您必须在绘图时维护您的列表,所以您必须清除先前的列表数据。
发布于 2014-01-03 10:33:40
看看这个..。我相信你有能力展示谷歌地图v2
查看decodePoly和drawPath在AsyncTask中的方法
"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
}
}
希望能帮上忙。干杯!
更新
看看这个..。为Google创建v2片段
还有检查这个..。如何使用google map V2在地图片段上绘制形状
更多的参考..。如何从google地图中的标记中获取屏幕坐标v2 android
发布于 2014-01-03 11:05:57
因此,我们确实有一些解决方案,在地图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
并从它的参数中获取坐标。希望这会有所帮助:)
https://stackoverflow.com/questions/20901141
复制相似问题