I use a customized info window so that I can achieve a gray background and white text color. Yet, I get a white frame around it. I want all of the Info Window to be gray, that is including its triangular edge that points to the spot.
I use this code in my Activity:
map.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override // Use default InfoWindow frame
public View getInfoWindow(Marker marker) { return null; }
#Override // Defines the contents of the InfoWindow
public View getInfoContents(Marker marker) {
View v = getLayoutInflater().inflate(R.layout.map_info_window, null);
TextView tv_location = (TextView) v.findViewById(R.id.tv_location);
tv_location.setText(marker.getTitle());
return v;
}});
and this is my layout:
<!--?xml version="1.0" encoding="utf-8"?-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map_info_window"
android:layout_width="match_parent"
android:background="#color/light_grey"
android:orientation="horizontal"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tv_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white" />
</LinearLayout>
You have to override the getInfoWindow () method and inflate you custom layout in that function.
From Documentation
public abstract View getInfoWindow (Marker marker)
Provides a custom info window for a marker. If this method returns a
view, it is used for the entire info window. If you change this view
after this method is called, those changes will not necessarily be
reflected in the rendered info window. If this method returns null ,
the default info window frame will be used, with contents provided by
getInfoContents(Marker).
#Override // Use default InfoWindow frame
public View getInfoWindow (Marker marker){
View v = getLayoutInflater().inflate(R.layout.map_info_window, null);
TextView tv_location = (TextView) v.findViewById(R.id.tv_location);
tv_location.setText(marker.getTitle());
return v;
}
#Override // Defines the contents of the InfoWindow
public View getInfoContents (Marker marker){
// TODO Auto-generated method stub
return null;
}
So i think you should reverse your function implementation.
Related
How to display marker infowindow when map loads? when im clicking the map name a new activity starts where the map loads.It shows the marker,the problem is i want to automatically display also the custom infowindow i created.Here's my code below: I will mark this answer for those who can fix this. thanks.
if (nameList.get(i).equals(selected)){
Marker marker = map.addMarker(new MarkerOptions()
.title(nameList.get(i))
.snippet(addressList.get(i))
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_location))
.position(new LatLng(latList.get(i), lngList.get(i))));
marker.showInfoWindow();
//Set Custom InfoWindow
map.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View myContentsView = getLayoutInflater().inflate(R.layout.map_info, null);
TextView tvTitle = ((TextView)myContentsView.findViewById(R.id.title));
tvTitle.setText(marker.getTitle());
TextView tvSnippet = ((TextView)myContentsView.findViewById(R.id.snippet));
tvSnippet.setText(marker.getSnippet());
TextView infoSnippet = (TextView)myContentsView.findViewById(R.id.moreinfo);
infoSnippet.setText("Click for more details.");
return myContentsView;
}
});
//Open New Activity
map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Intent intent = new Intent(SelectedPlaceActivity.this, PlaceDescriptionActivity.class);
intent.putExtra("placetitle", marker.getTitle().toString());
intent.putExtra("snippet", marker.getSnippet().toString());
startActivity(intent);
}
});
}
It seems that you need an InfoWindow adapter. See the following example:
map.setInfoWindowAdapter(new InfoWindowAdapter(){
// Use default InfoWindow frame
#Override
public View getInfoWindow(Marker marker) {
return null;
}
// Defines the contents of the InfoWindow
#Override
public View getInfoContents(Marker marker) {
// Getting view from the layout file info_window_layout
View v = getLayoutInflater().inflate(R.layout.custom_info_window, null);
// Getting reference to the TextView to set title
TextView note = (TextView) v.findViewById(R.id.note);
note.setText(marker.getTitle() );
return v;
}
});
As you can see, you need to create a custom layout. In my example:
<?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/note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textColor="#000000"/>
<ImageButton android:id="#+id/takeMeThere"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/note"
android:contentDescription="#string/directions"
android:src="#drawable/ic_action_directions"
android:background="#null"/>
</RelativeLayout>
Hope this helps
According to the documents of Google Maps for Android V2:
An info window allows you to display information to the user when they
tap on a marker on a map. By default, an info window is displayed when
a user taps on a marker if the marker has a title set. Only one info
window is displayed at a time. If a user clicks on another marker, the
current window will be hidden and the new info window will be
displayed. You can show an info window programmatically by calling
showInfoWindow() on the target marker. An info window can be hidden by
calling hideInfoWindow().
I am using a custom InfoWindow in my app. I have two question related to it.
Is it possible to make multiline snippet in InfoWindow
Say am adding some data lets say I need to show LATTITUDE and LONGITUDE when I click on marker. Normally if u set these values in snippet they appear on same line. I would like to show them on two line. Is that possible
I googled about multiline snippet and couldn't find anything much useful so came up with the idea of customising InfoWindow.
2.Below show is my custom InfoWindow which gives me NullPointerException
Getting exception from try-catch loop. I followed some code I found while googleing but it's not working.
private class MyCustomInfoWindow implements InfoWindowAdapter{
private View view;
public MyCustomInfoWindow(){
}
#Override
public View getInfoContents(Marker markr) {
// TODO Auto-generated method stub
return null;
}
#Override
public View getInfoWindow(Marker marker) {
// TODO Auto-generated method stub
view = getLayoutInflater().inflate(R.layout.mycustom_infowindow, null);
TextView marker_heading = (TextView)findViewById(R.id.marker_heading);
try{
String m_heading = marker.getId();
marker_heading.setText(m_heading);
}
catch(Exception exx){
Toast.makeText(getApplicationContext(), "getInfoWindow Error is " + marker_heading.length(), Toast.LENGTH_LONG).show();
}
return view;
}
}
My custom
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/marker_heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:typeface="serif"
android:textStyle="bold"
/>
</LinearLayout>
Using Google Maps V2
Could someone please tell me where am going wrong .
Use
TextView marker_heading = (TextView)view.findViewById(R.id.marker_heading);
to initialize marker_heading TextView instance because TextView is inside mycustom_infowindow layout
You should replace this
TextView marker_heading = (TextView)findViewById(R.id.marker_heading);
With
TextView marker_heading = (TextView)view.findViewById(R.id.marker_heading);
Use
TextView marker_heading = (TextView)view.findViewById(R.id.marker_heading);
you have to pass your View's object as a refernce to find id for TextView
I need custom info window with two clickable button as above.In it when more then marker and click any one of them then window should be open and when click on another marker another window should open and close previous window as well in single click.
is there any specific reason why google map v2 not support live component like button ,check box?
What you are trying to achieve is possible.
You can see the recipe in this answer: https://stackoverflow.com/a/15040761/2183804
And a working implementation on Google Play.
MainActivity.java
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends Activity {
private ViewGroup infoWindow;
private TextView infoTitle;
private TextView infoSnippet;
private Button infoButton1, infoButton2;
private OnInfoWindowElemTouchListener infoButtonListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapwrapperlauot);
final MapFragment mapFragment =
(MapFragment) getFragmentManager().findFragmentById(R.id.map);
final MapWrapperLayout mapWrapperLayout =
(MapWrapperLayout) findViewById(R.id.map_relative_layout);
final GoogleMap map = mapFragment.getMap();
mapWrapperLayout.init(map, getPixelsFromDp(this, 39 + 20));
final Marker ki = map.addMarker(new MarkerOptions()
.position(new LatLng(50.08, 14.43))
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.circles)));
infoWindow = (ViewGroup) getLayoutInflater()
.inflate(R.layout.activity_main, null);
infoButton1 = (Button) infoWindow.findViewById(R.id.b1);
infoButton2 = (Button) infoWindow.findViewById(R.id.b2);
infoButtonListener = new OnInfoWindowElemTouchListener(infoButton1,
getResources().getDrawable(R.drawable.ic_launcher),
getResources().getDrawable(R.drawable.ic_launcher)) {
#Override
protected void onClickConfirmed(View v, Marker marker) {
Toast.makeText(getApplicationContext(),
"click on button 1", Toast.LENGTH_LONG).show();
}
};
infoButton1.setOnTouchListener(infoButtonListener);
infoButtonListener = new OnInfoWindowElemTouchListener(infoButton2,
getResources().getDrawable(R.drawable.ic_launcher),
getResources().getDrawable(R.drawable.ic_launcher)) {
#Override
protected void onClickConfirmed(View v, Marker marker) {
Toast.makeText(getApplicationContext(),
"click on button 2", Toast.LENGTH_LONG).show();
}
};
infoButton2.setOnTouchListener(infoButtonListener);
infoWindow.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
map.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker marker) {
infoButtonListener.setMarker(marker);
mapWrapperLayout.setMarkerWithInfoWindow(marker, infoWindow);
return infoWindow;
}
#Override
public View getInfoContents(Marker marker) {
// Setting up the infoWindow with current's marker info
return null;
}
});
ki.showInfoWindow();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(50.08, 14.43), 15));
map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
}
public static int getPixelsFromDp(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
}
activity_main
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="#drawable/marker" >
<Button
android:id="#+id/b1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Button1"
android:layout_marginBottom="10dp" />
<Button
android:id="#+id/b2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Button2"
android:layout_marginBottom="10dp" />
</LinearLayout>
</RelativeLayout>
now copy the following files from the link https://stackoverflow.com/a/15040761/2183804
mapwrapperlauot (include your package name in tag)
MapWrapperLayout.java
OnInfoWindowElemTouchListener.java
It will work.
I have build a sample android studio project for this question.
output screen shots :-
Download full project source code Click here
Please note: you have to add your API key in Androidmanifest.xml
What you are trying to achieve is not possible. Even if you create an XML layout for your info-window, info window contents are rendered and presented as an image on the maps. So it can accept only one click listener for the whole window. You can't specify multiple click listeners for a window.
UPDATE:
From the Docs:
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.
There is actually a library that can resolve your problem and add an info window that is a live view and you can interact with it.
https://github.com/Appolica/InteractiveInfoWindowAndroid
In my android app, I have a info window for a marker I place on the map. I want to do these things:
Make the default marker bigger (its too small now)
When the info window shows up, the text in it is making the width too long. Is there a way I can set a maximum width on it?
How can I increase the font size for the title and text?
Can anyone show me how to do this?
Thanks.
Maybe a little late, but you need to create a new custom adapter you can take a look in here: How to change Google Maps marker window Info
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(com.google.android.gms.maps.model.Marker arg0) {
return null;
}
#Override
public View getInfoContents(com.google.android.gms.maps.model.Marker marker) {
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
View mView = null;
//using the id, you can store multiple types of markers on List's and change the layout
if (marker.getId().equals(end.getId())) {
mView = inflater.inflate(R.layout.custom_info_window, (ViewGroup) findViewById(R.id.map), false);
((TextView) mView.findViewById(R.id.txtTitle)).setText(marker.getTitle());
}else{
mView = inflater.inflate(R.layout.normal_info_window, (ViewGroup) findViewById(R.id.map), false);
((TextView) mView.findViewById(R.id.txtTitle)).setText(marker.getTitle());
((TextView) mView.findViewById(R.id.txtDescription)).setText(marker.getSnippet());
}
return mView;
}
});
mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
//do whatever you need
}
});
In te custom view you can modify the size of the font, and other things, for the first point the marker icon can be modified on the MarkerOptions.setIcon, where you can use one from your assets.
1: When you add the Marker to the map, you can set the icon in the MarkerOptions. Make your own icon and use that.
2 & 3: Set an onMarkerClickListener on your GoogleMap. In the callback, you can create and show your own info window view on the map (just make sure you return false from the onMarkerClick() callback)
I have a problem with marker on google maps api v2.
I would like to customize infoWindows with a WebView:
Here my code of InfoWindowAdapter
mMap.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker arg0) {
View v = getLayoutInflater().inflate(R.layout.info_window_layout, null);
TextView title = (TextView) v.findViewById(R.id.title_marker);
WebView snippet = (WebView) v.findViewById(R.id.item_snippet);
title.setText(arg0.getTitle());
snippet.setVisibility(WebView.VISIBLE);
snippet.loadData(arg0.getSnippet(),"text/html", "UTF-8");
return v;
}
});
And this is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/title_marker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<WebView
android:id="#+id/item_snippet"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
My problem is that I see the content into the TextView, but not the content into the WebView.
What i'm doing wrong?
Thanks a lot
You can't use a WebView directly. The reason is (source: official docs):
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.
You can try drawing the webview on a bitmap (after the content has been loaded) and supplying an ImageView with that bitmap in the InfoWindow adapter, but you will lose interactivity with the webview anyway.
after a lot of tests, googling and some reversing I can say that view you return in getInfoContents is used to render into a Bitmap and then hidden. The bitmap is then displayed via GL
I've found a workaround that can be fine for you.
private View mGhost;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mGhost = new View(this);
mGhost.setLayoutParams(new LayoutParams(0, 0));
mGhost.setVisibility(View.GONE);
....
}
public void onMapReady(GoogleMap map) // or whatever
{
map.setInfoWindowAdapter(new InfoWindowAdapter()
{
#Override
public View getInfoWindow(Marker marker)
{
return null;
}
#Override
public View getInfoContents(final Marker marker)
{
WebView webview = new WebView(MainActivity.this);
webview.loadUrl(marker.getSnippet());
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
AlertDialog alert = builder.setView(webview).create();
alert.show();
alert.getWindow().setLayout(200, 200);
mGhost.post(new Runnable()
{
#Override
public void run()
{
marker.hideInfoWindow();
}
});
return mGhost;
}
});
}
in this example I've used the snippet to store the url, It's not exactly what did you asked, but it may look similar.
Edit: the first version was recycling the WebView but it's not possible without some trick to remove it from the Alert, this revised version doesn't shows the InfoContents box below but has still an issue, when pressed it keeps a sort of state, and it believes the marker is clicked after closing the dialog.
You may use a layout that contains a WebView to decor a bit the window
Edit2: Reverted to something like the first version, a blank InfoContents box shows for bit I'm not sure it's avoidable.