In this page

MapView CameraPosition Method

This example shows CameraPosition Method on MapView

  1. CameraPosition Method

    1. target

    2. zoom

    3. bearing

    4. 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:

  1. 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:

  1. 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).

  2. 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.

  3. The onMapLongClick method is implemented to toggle the logging of camera changes when a long click event occurs on the map.

  4. 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.

  5. 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.

  6. 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.

DIDN'T FIND WHAT YOU LOOKING FOR?