在Google地图上用手指自由地绘图

我想实现一个自定义的模块,在Google Map上进行免费的绘图。 说到实现,我发现Google Map onDrag()callback函数总是会覆盖我自定义的onDrag()函数。 我不知道如何使用我的FrameLayout onDrag()来覆盖地图的点击和拖动动作。

这是我的工作:

XML:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:id="@+id/locinfo" android:layout_width="match_parent" android:layout_height="wrap_content" /> <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.example.androidmapsv2.CustomMapFragment" > </fragment> <FrameLayout android:id="@+id/fram_map" android:layout_width="match_parent" android:layout_height="match_parent" > </FrameLayout> </LinearLayout> 

CustomMapFragment.java

 package com.example.androidmapsv2; import com.google.android.gms.maps.MapFragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class CustomMapFragment extends MapFragment { 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; } } 

MainActivity.java

 package com.example.androidmapsv2; import java.util.ArrayList; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMapClickListener; import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener; import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.Projection; 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.Polygon; import com.google.android.gms.maps.model.PolygonOptions; import com.google.android.gms.maps.model.PolylineOptions; import android.app.Activity; import android.app.FragmentManager; import android.graphics.Color; import android.graphics.Point; import android.location.Location; import android.os.Bundle; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements OnMapClickListener { final int RQS_GooglePlayServices = 1; private GoogleMap myMap; Location myLocation; TextView tvLocInfo; ArrayList<LatLng> val = new ArrayList<LatLng>(); boolean markerClicked; PolygonOptions polygonOptions; Polygon polygon; FrameLayout fram_map; CustomMapFragment myMapFragment ; boolean Is_MAP_Moveable; Projection projection; public double latitude; public double longitude; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvLocInfo = (TextView)findViewById(R.id.locinfo); FragmentManager myFragmentManager = getFragmentManager(); myMapFragment = (CustomMapFragment)myFragmentManager.findFragmentById(R.id.map); if (myMapFragment != null) { myMapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap map) { loadMap(map); } }); fram_map = (FrameLayout) findViewById(R.id.fram_map); Is_MAP_Moveable = false; // to detect map is movable } else { Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show(); } } public void Draw_Map() { myMap.addPolyline(new PolylineOptions() .addAll(val) .color(Color.parseColor( "#0971b2")).width(10f)); } protected void loadMap(GoogleMap map) { // TODO Auto-generated method stub myMap = map; myMap.setMyLocationEnabled(true); myMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); myMap.setOnMapClickListener(this); //myMap.setOnMapLongClickListener(this); //myMap.setOnMarkerClickListener(this); markerClicked = false; 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 = myMap.getProjection(); Point x_y_points = new Point(x_co, y_co); LatLng latLng = myMap.getProjection().fromScreenLocation(x_y_points); latitude = latLng.latitude; longitude = latLng.longitude; switch (event.getAction()) { 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: v.performClick(); // finger leaves the screen Draw_Map(); break; } if (Is_MAP_Moveable == true) { return true; } else { return false; } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override protected void onResume() { super.onResume(); int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext()); if (resultCode == ConnectionResult.SUCCESS){ Toast.makeText(getApplicationContext(), "isGooglePlayServicesAvailable SUCCESS", Toast.LENGTH_LONG).show(); }else{ GooglePlayServicesUtil.getErrorDialog(resultCode, this, RQS_GooglePlayServices); } } @Override public void onMapClick(LatLng point) { Is_MAP_Moveable = !Is_MAP_Moveable; Toast.makeText(getApplicationContext(), Is_MAP_Moveable ? "drawing activated" : "drawing disabled", Toast.LENGTH_SHORT).show(); // tvLocInfo.setText(point.toString()); // myMap.animateCamera(CameraUpdateFactory.newLatLng(point)); // // markerClicked = false; } // @Override // public void onMapLongClick(LatLng point) { // tvLocInfo.setText("New marker added@" + point.toString()); // myMap.addMarker(new MarkerOptions().position(point).title(point.toString())); // // markerClicked = false; // } // // @Override // public boolean onMarkerClick(Marker marker) { // // if(markerClicked){ // // if(polygon != null){ // polygon.remove(); // polygon = null; // } // // polygonOptions.add(marker.getPosition()); // polygonOptions.strokeColor(Color.RED); // polygonOptions.fillColor(Color.BLUE); // polygon = myMap.addPolygon(polygonOptions); // }else{ // if(polygon != null){ // polygon.remove(); // polygon = null; // } // // polygonOptions = new PolygonOptions().add(marker.getPosition()); // markerClicked = true; // } // // return true; // } } 

Solutions Collecting From Web of "在Google地图上用手指自由地绘图"

一种方法是在地图上创build一个View并为此View创build一个OnTouchListener来截取地图的触摸:

activity_maps.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.google.android.gms.maps.SupportMapFragment" /> <View android:id="@+id/draggable" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" /> </RelativeLayout> 

MapsActivity.java

 public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { private GoogleMap mMap; private View draggableView; private List<LatLng> polylinePoints = new ArrayList<>(); private Polyline polyline; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); draggableView = findViewById(R.id.draggable); } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; draggableView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { LatLng position = mMap.getProjection().fromScreenLocation( new Point((int) motionEvent.getX(), (int) motionEvent.getY())); if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { if (polyline != null) { polyline.remove(); polyline = null; } polyline = mMap.addPolyline( new PolylineOptions().color(Color.RED).addAll(polylinePoints)); } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE){ polylinePoints.add(position); polyline.setPoints(polylinePoints); } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) { // Close the polyline? } return true; } }); } }