I want to implement a custom module for free drawing on Google Map. When it comes to the implementation, I have found that the Google Map onDrag()
callback and always overrides my custom onDrag()
function. I am not so sure how to use my FrameLayout
onDrag()
to override the map click and drag motion.
Here is my working:
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;
// }
}
Add line or shape. Select a layer and click where to start drawing. A layer can have 2,000 lines, shapes or places. Click each corner or bend of your line or shape. To move the map, click and hold the mouse.
Scribble Maps is an interesting mash-up that turns Google Maps into an online whiteboard. It adds common drawing and painting tools such as pencils, lines and colored brushes to the Google Maps interfaces so you can easily sketch freehand drawings, insert text, or even add custom shapes anywhere on the map.
My Maps in a browser: Plot the points > Draw a line > Add Driving Route. Use mouse to draw route. Mark current location: Create a map; type your address in the search bar. The Android My Maps app is no longer available; however, you can use My Maps in a mobile browser on your device.
To draw the line or shape you want, click a start point on the map and drag. Click an endpoint. Then, enter a description and properties. Click OK.
One way can be to create a View
over your map and create an OnTouchListener
for this View
to intercept map touches:
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;
}
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With