MapView CameraPosition Method
This example shows CameraPosition Method on MapView
-
CameraPosition Method
-
target
-
zoom
-
bearing
-
tilt
-

For all code examples, refer to Android Maps SDK Code Examples
activity_camera_position.xml view source
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:id="@+id/coordinator_layout"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent">
7
8 <ai.nextbillion.maps.core.MapView
9 android:id="@id/mapView"
10 android:layout_width="match_parent"
11 android:layout_height="match_parent"
12 app:nbmap_uiAttributionTintColor="@color/redAccent" />
13
14 <com.google.android.material.floatingactionbutton.FloatingActionButton
15 android:id="@+id/fab"
16 android:layout_width="wrap_content"
17 android:layout_height="wrap_content"
18 android:layout_gravity="end|bottom"
19 android:layout_margin="@dimen/fab_margin"
20 app:srcCompat="@drawable/ic_input"
21 app:backgroundTint="@android:color/white" />
22
23</androidx.coordinatorlayout.widget.CoordinatorLayout>
CameraPositionActivity view source
1package ai.nextbillion;
2
3import android.content.Context;
4import android.content.DialogInterface;
5import android.os.Bundle;
6import android.view.LayoutInflater;
7import android.view.View;
8import android.widget.SeekBar;
9import android.widget.TextView;
10import android.widget.Toast;
11
12import com.google.android.material.floatingactionbutton.FloatingActionButton;
13
14import ai.nextbillion.maps.camera.CameraPosition;
15import ai.nextbillion.maps.camera.CameraUpdateFactory;
16import ai.nextbillion.maps.core.MapView;
17import ai.nextbillion.maps.core.NextbillionMap;
18import ai.nextbillion.maps.core.OnMapReadyCallback;
19import ai.nextbillion.maps.geometry.LatLng;
20import androidx.annotation.IdRes;
21import androidx.annotation.NonNull;
22import androidx.appcompat.app.AlertDialog;
23import androidx.appcompat.app.AppCompatActivity;
24import androidx.core.content.ContextCompat;
25
26import static ai.nextbillion.maps.constants.GeometryConstants.MAX_LATITUDE;
27import static ai.nextbillion.maps.constants.GeometryConstants.MIN_LATITUDE;
28
29/**
30 * Test activity showcasing how to listen to camera change events.
31 */
32public class CameraPositionActivity extends AppCompatActivity implements OnMapReadyCallback, View.OnClickListener,
33 NextbillionMap.OnMapLongClickListener {
34
35 private MapView mapView;
36 private NextbillionMap nextbillionMap;
37 private FloatingActionButton fab;
38 private boolean logCameraChanges;
39
40 @Override
41 protected void onCreate(Bundle savedInstanceState) {
42 super.onCreate(savedInstanceState);
43 setContentView(R.layout.activity_camera_position);
44 mapView = findViewById(R.id.mapView);
45 mapView.onCreate(savedInstanceState);
46 mapView.getMapAsync(this);
47 }
48
49 @Override
50 public void onMapReady(@NonNull final NextbillionMap map) {
51 nextbillionMap = map;
52 map.setStyle(StyleConstants.LIGHT, style -> {
53 // add a listener to FAB
54 fab = findViewById(R.id.fab);
55 fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.palette_mint_100));
56 fab.setOnClickListener(this);
57
58 toggleLogCameraChanges();
59
60 // listen to long click events to toggle logging camera changes
61 nextbillionMap.addOnMapLongClickListener(this);
62 });
63 }
64
65 @Override
66 public boolean onMapLongClick(@NonNull LatLng point) {
67 toggleLogCameraChanges();
68 return false;
69 }
70
71 @Override
72 public void onClick(View view) {
73 Context context = view.getContext();
74 final View dialogContent = LayoutInflater.from(context).inflate(R.layout.dialog_camera_position, null);
75 AlertDialog.Builder builder = new AlertDialog.Builder(context);
76 builder.setTitle(R.string.dialog_camera_position);
77 builder.setView(onInflateDialogContent(dialogContent));
78 builder.setPositiveButton("Animate", new DialogClickListener(nextbillionMap, dialogContent));
79 builder.setNegativeButton("Cancel", null);
80 builder.setCancelable(false);
81 builder.show();
82 }
83
84 private void toggleLogCameraChanges() {
85 logCameraChanges = !logCameraChanges;
86 if (logCameraChanges) {
87 nextbillionMap.addOnCameraIdleListener(idleListener);
88 nextbillionMap.addOnCameraMoveCancelListener(moveCanceledListener);
89 nextbillionMap.addOnCameraMoveListener(moveListener);
90 nextbillionMap.addOnCameraMoveStartedListener(moveStartedListener);
91 } else {
92 nextbillionMap.removeOnCameraIdleListener(idleListener);
93 nextbillionMap.removeOnCameraMoveCancelListener(moveCanceledListener);
94 nextbillionMap.removeOnCameraMoveListener(moveListener);
95 nextbillionMap.removeOnCameraMoveStartedListener(moveStartedListener);
96 }
97 }
98
99 @Override
100 protected void onStart() {
101 super.onStart();
102 mapView.onStart();
103 }
104
105 @Override
106 protected void onResume() {
107 super.onResume();
108 mapView.onResume();
109 }
110
111 @Override
112 protected void onPause() {
113 super.onPause();
114 mapView.onPause();
115 }
116
117 @Override
118 protected void onStop() {
119 super.onStop();
120 mapView.onStop();
121 }
122
123 @Override
124 protected void onDestroy() {
125 super.onDestroy();
126 if (nextbillionMap != null) {
127 nextbillionMap.removeOnMapLongClickListener(this);
128 }
129 mapView.onDestroy();
130 }
131
132 @Override
133 protected void onSaveInstanceState(Bundle outState) {
134 super.onSaveInstanceState(outState);
135 mapView.onSaveInstanceState(outState);
136 }
137
138 private View onInflateDialogContent(View view) {
139 linkTextView(view, R.id.value_lat, R.id.seekbar_lat, new LatLngChangeListener(), 180 + 38);
140 linkTextView(view, R.id.value_lon, R.id.seekbar_lon, new LatLngChangeListener(), 180 - 77);
141 linkTextView(view, R.id.value_zoom, R.id.seekbar_zoom, new ValueChangeListener(), 6);
142 linkTextView(view, R.id.value_bearing, R.id.seekbar_bearing, new ValueChangeListener(), 90);
143 linkTextView(view, R.id.value_tilt, R.id.seekbar_tilt, new ValueChangeListener(), 40);
144 return view;
145 }
146
147 private void linkTextView(
148 View view, @IdRes int textViewRes, @IdRes int seekBarRes, ValueChangeListener listener, int defaultValue) {
149 final TextView value = (TextView) view.findViewById(textViewRes);
150 SeekBar seekBar = (SeekBar) view.findViewById(seekBarRes);
151 listener.setLinkedValueView(value);
152 seekBar.setOnSeekBarChangeListener(listener);
153 seekBar.setProgress(defaultValue);
154 }
155
156 private NextbillionMap.OnCameraIdleListener idleListener = new NextbillionMap.OnCameraIdleListener() {
157 @Override
158 public void onCameraIdle() {
159 fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_green_dark));
160 }
161 };
162
163 private NextbillionMap.OnCameraMoveListener moveListener = new NextbillionMap.OnCameraMoveListener() {
164 @Override
165 public void onCameraMove() {
166 fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_orange_dark));
167 }
168 };
169
170 private NextbillionMap.OnCameraMoveCanceledListener moveCanceledListener = () -> {};
171
172 private NextbillionMap.OnCameraMoveStartedListener moveStartedListener = new NextbillionMap.OnCameraMoveStartedListener() {
173
174 private final String[] REASONS = {"REASON_API_GESTURE", "REASON_DEVELOPER_ANIMATION", "REASON_API_ANIMATION"};
175
176 @Override
177 public void onCameraMoveStarted(int reason) {
178 // reason ranges from 1 <-> 3
179 fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_red_dark));
180 }
181 };
182
183 private class ValueChangeListener implements SeekBar.OnSeekBarChangeListener {
184
185 protected TextView textView;
186
187 public void setLinkedValueView(TextView textView) {
188 this.textView = textView;
189 }
190
191 @Override
192 public void onStartTrackingTouch(SeekBar seekBar) {
193
194 }
195
196 @Override
197 public void onStopTrackingTouch(SeekBar seekBar) {
198
199 }
200
201 @Override
202 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
203 textView.setText(String.valueOf(progress));
204 }
205 }
206
207 private class LatLngChangeListener extends ValueChangeListener {
208
209 @Override
210 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
211 super.onProgressChanged(seekBar, progress - 180, fromUser);
212 }
213 }
214
215 private static class DialogClickListener implements DialogInterface.OnClickListener {
216
217 private NextbillionMap nextbillionMap;
218 private View dialogContent;
219
220 public DialogClickListener(NextbillionMap nextbillionMap, View view) {
221 this.nextbillionMap = nextbillionMap;
222 this.dialogContent = view;
223 }
224
225 @Override
226 public void onClick(DialogInterface dialog, int which) {
227 double latitude = Double.parseDouble(
228 ((TextView) dialogContent.findViewById(R.id.value_lat)).getText().toString());
229 double longitude = Double.parseDouble(
230 ((TextView) dialogContent.findViewById(R.id.value_lon)).getText().toString());
231 double zoom = Double.parseDouble(
232 ((TextView) dialogContent.findViewById(R.id.value_zoom)).getText().toString());
233 double bearing = Double.parseDouble(
234 ((TextView) dialogContent.findViewById(R.id.value_bearing)).getText().toString());
235 double tilt = Double.parseDouble(
236 ((TextView) dialogContent.findViewById(R.id.value_tilt)).getText().toString());
237
238 if (latitude < MIN_LATITUDE || latitude > MAX_LATITUDE) {
239 Toast.makeText(dialogContent.getContext(), "latitude value must be set "
240 + " between " + MIN_LATITUDE + " and " + MAX_LATITUDE,
241 Toast.LENGTH_SHORT).show();
242 return;
243 }
244
245 CameraPosition cameraPosition = new CameraPosition.Builder()
246 .target(new LatLng(latitude, longitude))
247 .zoom(zoom)
248 .bearing(bearing)
249 .tilt(tilt)
250 .build();
251
252 nextbillionMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000,
253 new NextbillionMap.CancelableCallback() {
254 @Override
255 public void onCancel() {
256 }
257
258 @Override
259 public void onFinish() {
260 }
261 });
262 }
263 }
264}
The code is an activity called CameraPositionActivity that demonstrates how to listen to camera change events in a map view. It uses the Nextbillion Maps SDK for Android.
initMapView:
- The map view is initialized in the onCreate method by setting the content view to the layout file activity_camera_position.xml. The map view is found using findViewById and the getMapAsync method is called to set the callback for when the map is ready.
Operations on Camera Position:
-
The onMapReady method is implemented to receive the NextbillionMap object when it is ready. The map style is set to StyleConstants.SATELLITE_STREETS, and a listener is added to a floating action button (FAB).
-
The toggleLogCameraChanges method is used to toggle the logging of camera changes. When logging is enabled, listeners for camera events are added to the map. When logging is disabled, the listeners are removed.
-
The onMapLongClick method is implemented to toggle the logging of camera changes when a long click event occurs on the map.
-
The onClick method is implemented to show a dialog when the FAB is clicked. The dialog allows the user to set the camera position parameters (latitude, longitude, zoom, bearing, and tilt) and animates the camera to the new position when the "Animate" button is clicked.
-
The LatLngChangeListener class extends ValueChangeListener and adjusts the latitude value by subtracting 180, as the seek bar range is from 0 to 360 but latitude ranges from -90 to 90.
-
The DialogClickListener class is an implementation of DialogInterface.OnClickListener that retrieves the camera position parameters from the dialog content and animates the camera to the new position using nextbillionMap.animateCamera.
Additionally, the code includes lifecycle methods (onStart, onResume, onPause, onStop, onDestroy, onSaveInstanceState) to manage the state of the map view and release resources properly.
The activity demonstrates how to initialize a map view, handle camera change events, and interact with the camera position using a dialog.