custom InfoWindow
This example shows how to Add a Marker with a Custom Info Window
-
Add a Custom view Marker with CustomMarkerOptions
-
Custom the info widow of the marker using mMap.setInfoWindowAdapter

For all code examples, refer to Android Maps SDK Code Examples
activity_animate_markers.xml view source
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".MainActivity">
8
9 <ai.nextbillion.maps.core.MapView
10 android:id="@+id/map_view"
11 android:layout_width="match_parent"
12 android:layout_height="match_parent"
13 app:nbmap_uiAttribution="false"
14 app:nbmap_cameraTargetLat="53.550813508267716"
15 app:nbmap_cameraTargetLng="9.992248999933745"
16 app:nbmap_cameraZoom="15" />
17
18 <ImageView
19 android:id="@+id/iv_back"
20 android:layout_width="40dp"
21 android:layout_height="40dp"
22 android:layout_marginLeft="16dp"
23 app:layout_constraintTop_toTopOf="parent"
24 app:layout_constraintLeft_toLeftOf="parent"
25 android:layout_marginTop="16dp"
26 android:background="@drawable/circle_white_bg"
27 android:src="@drawable/icon_back"
28 app:tint="@color/color_back_icon"/>
29
30</androidx.constraintlayout.widget.ConstraintLayout>
CustomInfoWindowActivity view source
1package ai.nextbillion;
2
3import android.graphics.Bitmap;
4import android.graphics.Color;
5import android.os.Bundle;
6import android.os.Parcel;
7import android.os.Parcelable;
8import android.view.LayoutInflater;
9import android.view.View;
10import android.widget.ImageView;
11import android.widget.TextView;
12
13import ai.nextbillion.maps.annotations.BaseMarkerOptions;
14import ai.nextbillion.maps.annotations.Icon;
15import ai.nextbillion.maps.annotations.IconFactory;
16import ai.nextbillion.maps.annotations.Marker;
17import ai.nextbillion.maps.core.MapView;
18import ai.nextbillion.maps.core.NextbillionMap;
19import ai.nextbillion.maps.core.OnMapReadyCallback;
20import ai.nextbillion.maps.core.Style;
21import ai.nextbillion.maps.geometry.LatLng;
22import ai.nextbillion.utils.SymbolGenerator;
23import androidx.annotation.NonNull;
24import androidx.annotation.Nullable;
25import androidx.appcompat.app.AppCompatActivity;
26
27public class CustomInfoWindowActivity extends AppCompatActivity implements OnMapReadyCallback {
28
29 private MapView mapView;
30 private NextbillionMap mMap;
31 private ImageView ivBack;
32
33 @Override
34 protected void onCreate(Bundle savedInstanceState) {
35 super.onCreate(savedInstanceState);
36 setContentView(R.layout.activity_animate_markers);
37
38 ivBack = findViewById(R.id.iv_back);
39 mapView = findViewById(R.id.map_view);
40 mapView.onCreate(savedInstanceState);
41 mapView.getMapAsync(this);
42
43 ivBack.setOnClickListener(v -> finish());
44 }
45
46 @Override
47 public void onMapReady(@NonNull NextbillionMap nextbillionMap) {
48 mMap = nextbillionMap;
49 mMap.getStyle(new Style.OnStyleLoaded() {
50 @Override
51 public void onStyleLoaded(@NonNull Style style) {
52 customiseInfoWindow();
53 addMarker();
54 }
55 });
56 }
57
58
59 ///////////////////////////////////////////////////////////////////////////
60 //
61 ///////////////////////////////////////////////////////////////////////////
62
63 private Bitmap generateTextIcon() {
64// View view = LayoutInflater.from(this).inflate(R.layout.text_marker_layout, mapView, false);
65 View view = LayoutInflater.from(this).inflate(R.layout.custom_marker_layout, mapView, false);
66 return SymbolGenerator.generate(view);
67 }
68
69 private void addMarker() {
70 Bitmap iconBitmap = generateTextIcon();
71 Icon icon = IconFactory.getInstance(this).fromBitmap(iconBitmap);
72 mMap.addMarker(new CustomMarkerOptions().icon(icon).position(new LatLng(53.55095026373886, 9.992248999933745)));
73 }
74
75
76 ///////////////////////////////////////////////////////////////////////////
77 // Customise InfoWindow
78 ///////////////////////////////////////////////////////////////////////////
79
80 private void customiseInfoWindow() {
81 mMap.setInfoWindowAdapter(new NextbillionMap.InfoWindowAdapter() {
82 @Nullable
83 @Override
84 public View getInfoWindow(@NonNull Marker marker) {
85 String title = marker.getTitle();
86 if (marker instanceof CustomMarker) {
87 View infoWidow = LayoutInflater.from(CustomInfoWindowActivity.this).inflate(R.layout.custom_info_window, mapView, false);
88 TextView infoText = infoWidow.findViewById(R.id.info_text);
89// int color = ((CustomMarker) marker).getInfoWindowColor();
90// TextView textView = defaultTextView(title);
91// textView.setBackgroundColor(color);
92 return infoWidow;
93 }
94
95 return defaultTextView(title);
96 }
97 });
98 }
99
100 private TextView defaultTextView(String text) {
101 TextView textView = new TextView(this);
102 int sixteenDp = (int) getResources().getDimension(R.dimen.attr_margin);
103 textView.setText(text);
104 textView.setTextColor(Color.WHITE);
105 textView.setPadding(sixteenDp, sixteenDp, sixteenDp, sixteenDp);
106 return textView;
107 }
108
109 static class CustomMarker extends Marker {
110
111 private final int infoWindowColor;
112
113 public CustomMarker(BaseMarkerOptions baseMarkerOptions, int color) {
114 super(baseMarkerOptions);
115 infoWindowColor = color;
116 }
117
118 public int getInfoWindowColor() {
119 return infoWindowColor;
120 }
121 }
122
123 static class CustomMarkerOptions extends BaseMarkerOptions<CustomMarker, CustomMarkerOptions> {
124
125 private int color;
126
127 public CustomMarkerOptions() {
128 }
129
130 public CustomMarkerOptions infoWindowColor(int color) {
131 this.color = color;
132 return this;
133 }
134
135 @Override
136 public CustomMarkerOptions getThis() {
137 return this;
138 }
139
140 @Override
141 public CustomMarker getMarker() {
142 return new CustomMarker(this, color);
143 }
144
145 private CustomMarkerOptions(Parcel in) {
146 position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
147 snippet(in.readString());
148 String iconId = in.readString();
149 Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
150 Icon icon = IconFactory.recreate(iconId, iconBitmap);
151 icon(icon);
152 title(in.readString());
153 infoWindowColor(in.readInt());
154 }
155
156 public static final Parcelable.Creator<CustomMarkerOptions> CREATOR
157 = new Parcelable.Creator<CustomMarkerOptions>() {
158 public CustomMarkerOptions createFromParcel(Parcel in) {
159 return new CustomMarkerOptions(in);
160 }
161
162 public CustomMarkerOptions[] newArray(int size) {
163 return new CustomMarkerOptions[size];
164 }
165 };
166
167 @Override
168 public int describeContents() {
169 return 0;
170 }
171
172 @Override
173 public void writeToParcel(Parcel out, int flags) {
174 out.writeParcelable(position, flags);
175 out.writeString(snippet);
176 out.writeString(icon.getId());
177 out.writeParcelable(icon.getBitmap(), flags);
178 out.writeString(title);
179 out.writeInt(color);
180 }
181 }
182
183 ///////////////////////////////////////////////////////////////////////////
184 // Lifecycle
185 ///////////////////////////////////////////////////////////////////////////
186
187 @Override
188 protected void onStart() {
189 super.onStart();
190 mapView.onStart();
191 }
192
193 @Override
194 protected void onResume() {
195 super.onResume();
196 mapView.onResume();
197 }
198
199 @Override
200 protected void onPause() {
201 super.onPause();
202 mapView.onPause();
203 }
204
205 @Override
206 protected void onStop() {
207 super.onStop();
208 mapView.onStop();
209 }
210
211 @Override
212 protected void onSaveInstanceState(@NonNull Bundle outState) {
213 super.onSaveInstanceState(outState);
214 mapView.onSaveInstanceState(outState);
215 }
216
217 @Override
218 protected void onDestroy() {
219 super.onDestroy();
220 mapView.onDestroy();
221 }
222
223 @Override
224 public void onLowMemory() {
225 super.onLowMemory();
226 mapView.onLowMemory();
227 }
228}
The given code is an Android activity that demonstrates how to initialize a MapView and add a marker with a custom info window.
Initializing the MapView:
-
The MapView is instantiated and initialized in the onCreate() method using findViewById().
-
The map is asynchronously loaded using getMapAsync() and the initialization of the map is done in the callback.
Adding a Marker with a Custom Info Window:
-
The addMarker method is responsible for adding a marker to the map.
-
First, a custom icon for the marker is generated using the generateTextIcon method.
-
Then, an instance of the Icon is created from the generated bitmap icon.
-
Finally, the mMap object (NextbillionMap) adds a marker with the custom icon and specified position.
Customizing the Info Window:
-
The customiseInfoWindow method is used to customize the info window appearance.
-
It sets an info window adapter for the map using mMap.setInfoWindowAdapter.
-
In the adapter's getInfoWindow method, a custom info window view is inflated and returned if the marker is an instance of CustomMarker.
-
Otherwise, a default text view with the marker's title is returned.
The code also includes various lifecycle methods (onStart, onResume, onPause, onStop, onSaveInstanceState, onDestroy, onLowMemory) that should be implemented when using the MapView to properly manage its lifecycle and handle configuration changes.
The code includes additional classes (CustomMarker, CustomMarkerOptions) for creating custom markers with custom properties, such as info window color. These classes extend the base marker classes provided by the Nextbillion Maps SDK.