I wish to add a marker to a googleMap with an editable title and snippet. The marker should appear when the user does a long click on the map and then the marker should appear showing a title of something like "click to edit".
The code is all up and running except that I can not figure out how to get the title to appear the moment the marker is created. I can only make it appear with a subsequent click on the marker. I can not see anything within MarkerOptions that allows me to do this. Did I miss something?
The option your looking for is not in MarkerOptions it is a function of the Marker itself. Here's a link to the related docs
marker.showInfoWindow();
To call this method you need to have the marker, or a reference to it. If you're doing this on creation it should be easy. Otherwise just store your makers in some collection - like a HashMap so they are easy to find - and you can display the info window whenever you want.
In case you want to display your marker's title and snippet in your own custom way - you may set it in the onMapReadyCallback.
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View view = getLayoutInflater().inflate(R.layout.marker_info, null);
TextView textViewTitle = (TextView) view.findViewById(R.id.marker_title);
textViewTitle.setText(marker.getTitle());
TextView textViewSnippet = (TextView) view.findViewById(R.id.marker_snippet);
textViewSnippet.setText(marker.getSnippet());
return view;
}
});
And here is my layout file for the same.
marker_info.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/marker_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:gravity="center"/>
<TextView
android:id="#+id/marker_snippet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
</LinearLayout>
Related
Question
Why does my custom infowindow not 'inflate' after a configuration change?
Summary
I have an app that places a marker on a map using MarkerManager, and sets a custom info-window using setInfoWindowAdapter.
After loading the app and clicking on the marker, the info-window correctly displays my custom layout.
However, after rotating the app so that the configuration changes, selecting the marker no longer displays the custom info-window, and instead only displays the generic 'title'.
What have I missed in all the hours of reading and tutorials that means I'm not correctly implementing this?
Code
Here is a stripped-down version of my app to replicate the issue
MapsActivity
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
MarkerManager.Collection mMarkerManagerCollection;
#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);
if(savedInstanceState == null){
mapFragment.setRetainInstance(true); // maintains the map fragment on orientation changes
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
MarkerManager mMarkerManager = new MarkerManager(mMap);
mMap.setInfoWindowAdapter(mMarkerManager);
mMarkerManagerCollection = mMarkerManager.newCollection("myMarker");
mMarkerManagerCollection.setOnInfoWindowAdapter(new GoogleMap.InfoWindowAdapter(){
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View v = getLayoutInflater().inflate(R.layout.info_window, null);
TextView tv = (TextView) v.findViewById(R.id.myTv);
tv.setText("hello world, this is my marker");
return v;
}
});
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
MarkerOptions options = new MarkerOptions()
.position(sydney)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))
.flat(true)
.title("Marker in Sydney");
Marker marker = mMarkerManagerCollection.addMarker(options);
marker.setTag("test marker");
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
info_window.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="93dp"
android:layout_height="96dp"
android:id="#+id/rect_load"
android:padding="2dp"
android:src="#mipmap/ic_launcher"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/myTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="myText"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Gradle
compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.google.android.gms:play-services:9.8.0'
compile 'com.google.maps.android:android-maps-utils:0.4'
compile 'com.google.android.gms:play-services:9.8.0'
The problem is that you are creating and populating a new MarkerManager on each onMapReady call. As onMapReady gets called when the orientation changes but you are not removing old markers, the map has two markers on the same position.
When you click the marker after the orientation changes, the old marker is triggered and you see the default behaviour (show title). If you click the marker again you will see your info window.
One possible solution can be calling mMap.clear(); on the onMapReady before adding markers.
I'm developing an app using lots of markers placed on the map, and I'm using a custom ClusterRenderer to show them.
Problem is that I can't draw the cluster's size in the center of the custom marker icon, please see attached screenshot.
I've tried adding contentPadding to the IconGenerator, but still no luck, because of the changing number of digits shown. Could you please help me center the text on the generated icon?
Code:
IconGenerator clusterIconGenerator = new IconGenerator(context);
clusterIcon = context.getResources().getDrawable(R.drawable.map_cluster);
clusterIconGenerator.setBackground(clusterIcon);
#Override
protected void onBeforeClusterRendered(Cluster<MyType> cluster, MarkerOptions markerOptions) {
Bitmap clusterIcon = clusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(clusterIcon));
}
UPDATE
starting Apr 1, 2016 a prefix has been added to the Resources of the library
so the id="text" has been changed to "amu_text".
As stated in the library documentation :
setContentView public void setContentView(View contentView) Sets the child view for the icon. If the view contains a
TextView with the id "amu_text", operations such as
setTextAppearance(Context, int) and makeIcon(String) will operate
upon that TextView .
#Override
protected void onBeforeClusterRendered(Cluster<Dashboard_Marker> cluster, MarkerOptions markerOptions) {
IconGenerator TextMarkerGen = new IconGenerator(context);
Drawable marker;
int ClusterSize = cluster.getSize();
marker = context.getResources().getDrawable(R.drawable.cluster_red);
TextMarkerGen.setBackground(marker);
LayoutInflater myInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = myInflater.inflate(R.layout.cluster_view, null, false);
TextMarkerGen.setContentView(activityView);
TextMarkerGen.makeIcon(String.valueOf(cluster.getSize()));
BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(TextMarkerGen.makeIcon());
markerOptions.icon(icon);
}
with the layout cluster_view as :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:weightSum="1">
<TextView
android:layout_width="61dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:textColor="#000000"
android:id="#+id/amu_text"
android:layout_marginTop="13dp"
android:gravity="center" />
</LinearLayout>
note :: the layout must contain one text view with an id = "amu_text" in order for the icon generator to accept it , manipulate all the positioning you want in the layout .
I want to set fixed marker in the center point of mapview while dragging map.It has been done at android Map V1 google mapview. But now it's deprecated.Now my question is, is it possible in android Map V2 google mapview ?(I have tried.but map doesn't show)
So you want something like a cross-hairs on the center of map, right?
I have not used MapView. But I have used Map Fragment, and the way i implement a fix marker on the map is use a ImageView, So you will end up with something like below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/fragment1"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/cross_hairs" />
</RelativeLayout>
You could swap the MapFragment with MapView.
Placing the marker on the map will be inefficient, since you will need to keep updating the marker when the user pans the map.
Hope it helps!
I'm betting you used getMapCenter() which, as per Google Maps for Android v2, no longer available to use. But no worries, just use this:
GoogleMap.getCameraPosition().target
It will return a LatLng object which basically represents the center of the map. You can then use it to reposition the marker to the center every time there's a drag event by assigning an OnCameraChangedListener to your GoogleMap.
yourGMapInstance.setOnCameraChangeListener(new OnCameraChangedListener() {
#Override
public void onCameraChange (CameraPosition position) {
// Get the center of the Map.
LatLng centerOfMap = yourGMapInstance.getCameraPosition().target;
// Update your Marker's position to the center of the Map.
yourMarkerInstance.setPosition(centerOfMap);
}
});
There. I hope this helped!
Notice that setOnCameraChangeListener() has been deprecated, so you can use the new camera listeners (OnCameraIdleListener, OnCameraMoveListener, OnCameraMoveStartedListener, OnCameraMoveCanceledListener), for example:
map.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
// Get the center of the map
LatLng center = map.getCameraPosition().target;
......
}
});
for more information, read this: https://developers.google.com/maps/documentation/android-api/events
Simply goto the XML File: Add Image View in map fragment and set the gravity to center. Then goto the Java File and add the following java code into your onMayReady Function:
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toTopOf="#+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/linearLayout2" />
<ImageView
android:id="#+id/imageView_map_marker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="17dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:layout_gravity="center"
android:tooltipText="Select Location"
app:srcCompat="#drawable/ic_baseline_location_red" />
mMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
mMap.clear();
binding.imageViewMapMarker.setVisibility(View.VISIBLE);
}
});
mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
#Override
public void onCameraIdle() {
binding.imageViewMapMarker.setVisibility(View.GONE);
selectedLatitude=mMap.getCameraPosition().target.latitude;
selectedLongitude=mMap.getCameraPosition().target.longitude;
MarkerOptions marker = new MarkerOptions().position(mMap.getCameraPosition().target).title("")
.icon(bitmapDescriptorFromVector(getApplicationContext(), R.drawable.ic_baseline_location_red));
mMap.addMarker(marker);
}
});
How can I change google map my location default button?
I set my location enable and map draw standard image to find location, is it possible to change default image?
See below xml file to custom button:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/maps"
android:name="pl.mg6.android.maps.extensions.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp" >
<ImageView
android:id="#+id/imgMyLocation"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="fitXY"
android:src="#drawable/track_my_location" />
</LinearLayout>
</RelativeLayout>
Then in java class, declare your location button:
private ImageView imgMyLocation;
imgMyLocation = (ImageView) findViewById(R.id.imgMyLocation);
Click Event:
imgMyLocation.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
getMyLocation();
}
Get Location Method, in that just pass your current latitude and longitude.
private void getMyLocation() {
LatLng latLng = new LatLng(Double.parseDouble(getLatitude()), Double.parseDouble(getLongitude()));
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 18);
googleMap.animateCamera(cameraUpdate);
}
});
With a simple trick, you can replace the my location button with a custom one.
Customize the Layout of your new button.
Set my location enabled in maps api.
Hide default button of my location.
call click method of my location on your custom button click.
1. Customize the layout of your new button
add a new button to your desired location in layout file of map activity.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MapsActivity" />
<ImageView
android:id="#+id/ic_location"
android:layout_width="18dp"
android:layout_height="18dp"
android:src="#drawable/ic_location"
android:layout_marginRight="8dp"
android:layout_marginBottom="18dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
2. Set my location enabled in maps api
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Enable My Location
mMap.setMyLocationEnabled(true);
/* and DON'T disable the default location button*/
}
3. Hide default button of my location.
//Create field for map button.
private View locationButton;
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMyLocationEnabled(true);
// get your maps fragment
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
// Extract My Location View from maps fragment
locationButton = mapFragment.getView().findViewById(0x2);
// Change the visibility of my location button
if(locationButton != null)
locationButton.setVisibility(View.GONE);
}
4. call click method of my location on your custom button click.
findViewById(R.id.ic_location).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mMap != null)
{
if(locationButton != null)
locationButton.callOnClick();
}
}
});
If you want to retain the smoothness of the default My Location button but not the look, call the following lines:
//Make sure you have explicit permission/catch SecurityException
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
Now you can start & stop location updates while keeping the default behavior
This might be useful to someone who is looking for changing the location icon directly, instead of using any trick or workaround:
locationButton = (mapView.findViewById<View>(Integer.parseInt("1")).parent as View)
.findViewById<ImageView>(Integer.parseInt("2"))
locationButton.setImageResource(R.drawable.ic_location_current)`
Here findViewById<ImageView> is the right thing to be done.
I get the default ImageView of my location using tag instead of idfor preventingExpected resource of type id` lint warning -
ImageView imageView = ((ImageView)mapFragment.getView().findViewWithTag("GoogleMapMyLocationButton"));
Then you can manipulate the imageView then.
imageView.setImageResource(R.drawable.icon_custom_location);
I want the string in my snippet to be aligned to the center.
Also, line breakers (\n) in the snippet are converted to spaces, is there a way to insert line breakers?
My relevant code:
GoogleMap map = ...
map.addMarker(new MarkerOptions().position(pos)
.title("title")
.snippet("body \n and mind");
Thanks
Using some examples, as well as answers from: custom info window adapter with custom data in map v2, I've come across the following solution:
marker.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center" />
</RelativeLayout>
Java:
map.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View v = getLayoutInflater().inflate(R.layout.marker, null);
TextView info= (TextView) v.findViewById(R.id.info);
info.setText(marker.getPosition().toString());
return v;
}
});