经过整整一天的研究和测试,我找到了一个解决方案。实际上,我找到了两种解决此问题的方法,但我建议使用替代方案2,因为与替代方案1相比,它真的非常简单。
实际上,在TheLittleNaruto、AndroidHacker和其他一些开发者的帮助下,我找到了替代方案1,而在Khan的帮助下,我找到了替代方案2,所以感谢大家。
替代方案1
如何在Map V2中绘制自由样式多边形(就像我们可以在Map V1中做的那样)?在Map V2中可行吗?
是的,这是可行的,但您无法直接在地图上获得OnTouch()
和OnDraw()
。因此,我们必须想出其他方法来实现这一点。
是否有任何技巧或替代方法可以实现这一点,如果有,如何实现?
是的,Google Map V2不支持在使用class="com.google.android.gms.maps.SupportMapFragment"
的地图上使用OnTouch()
或OnDraw()
,因此我们必须计划创建一个自定义片段。
是否可以返回具有触摸事件的Lat-long数组?
是的,如果我们创建任何自定义地图片段并使用它,我们可以在地图上获得Touch或Drag事件。
如何在setOnDragListener上根据屏幕坐标获取纬度和经度?
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();
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);
}
});
它是如何工作的?
正如我之前提到的,我们需要创建一个自定义根视图,并使用它来获取地图上的触摸或拖动事件。
步骤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
->
根映射(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);
}
});
}}
参考 Link1,Link2
到目前为止,我已经能够根据X,Y屏幕坐标获取LatLong。现在我只需要将其存储在数组中。该数组将用于在地图上绘制,最终看起来像一个自由形状的多边形。
希望这一定会对你有所帮助。
更新:
备选方案2
如我们所知,Frame layout 是一个透明的布局,因此我使用 Frame Layout 实现了这个功能。
在这种情况下,无需创建自定义片段。我只是使用Frame Layout作为根布局。因此,基本上我将在根布局中获得触摸事件,就像我们之前在自定义片段中获得的那样返回屏幕坐标。
现在,我在“Free Draw”中创建了一个按钮。因此,当您单击该按钮时,可以在地图上移动手指并绘制自由手多边形,并且这将禁用地图在屏幕上的可移动性。当您重新单击同一按钮时,屏幕进入理想模式。
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;
}
});
通过 Frame Layout 的触摸点击,并借助它来完成某些任务。
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:
val.add(new LatLng(latitude, longitude));
case MotionEvent.ACTION_MOVE:
val.add(new LatLng(latitude, longitude));
case MotionEvent.ACTION_UP:
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);
}
然而,现在您必须在绘图时保持列表的更新,因此您需要清除先前的列表数据。