Launch Custom NavigationView

A complete turn-by-turn experience using custom NavigationView

This example shows:

  • How to fetch a route using RouteFetcher.getRoute with RouteRequestParams.Builder

  • How to initialize a NavigationView and bind it to the activity lifecycle

  • How to config NavEngineConfig.Builder and NavViewConfig.Builder in the onNavigationReady() callback

  • How to start navigation using navigationView.startNavigation

docs-image

For all code examples, refer to Navigation Code Examples

activity_custom_navigation.xml view source

1
<?xml version="1.0" encoding="utf-8"?>
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
android:layout_width="match_parent"
4
android:layout_height="match_parent"
5
android:orientation="vertical"
6
android:padding="10dp">
7
8
<LinearLayout
9
android:layout_width="wrap_content"
10
android:layout_height="wrap_content">
11
<Button
12
android:id="@+id/fetchRoute"
13
android:layout_width="wrap_content"
14
android:layout_height="wrap_content"
15
android:text="@string/fetch_route"/>
16
17
<Button
18
android:id="@+id/startNav"
19
android:layout_width="wrap_content"
20
android:layout_height="wrap_content"
21
android:layout_marginLeft="15dp"
22
android:text="@string/start_navigation"/>
23
</LinearLayout>
24
25
<TextView
26
android:id="@+id/routeGeometry"
27
android:layout_width="wrap_content"
28
android:layout_height="wrap_content"
29
android:layout_marginTop="10dp"/>
30
31
<ProgressBar
32
android:id="@+id/progress"
33
android:visibility="gone"
34
android:layout_width="wrap_content"
35
android:layout_height="wrap_content"
36
android:layout_gravity="center"/>
37
38
</LinearLayout>

activity_navigation_view.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
<ai.nextbillion.navigation.ui.NavigationView
8
android:id="@+id/navigation_view"
9
app:navigationLightTheme="@style/Theme.CustomNavigationLight"
10
android:layout_width="match_parent"
11
android:layout_height="match_parent"/>
12
13
</androidx.constraintlayout.widget.ConstraintLayout>

CustomNavigationActivity view source

1
package ai.nextbillion.navigation.demo.activity;
2
3
import android.content.Intent;
4
import android.os.Bundle;
5
import android.view.View;
6
import android.widget.Button;
7
import android.widget.ProgressBar;
8
import android.widget.TextView;
9
10
import java.io.Serializable;
11
import java.util.List;
12
13
import ai.nextbillion.kits.directions.models.DirectionsResponse;
14
import ai.nextbillion.kits.directions.models.DirectionsRoute;
15
import ai.nextbillion.kits.directions.models.RouteRequestParams;
16
import ai.nextbillion.kits.geojson.Point;
17
import ai.nextbillion.navigation.core.routefetcher.RouteFetcher;
18
import ai.nextbillion.navigation.demo.R;
19
import androidx.appcompat.app.AppCompatActivity;
20
import retrofit2.Call;
21
import retrofit2.Callback;
22
import retrofit2.Response;
23
24
public class CustomNavigationActivity extends AppCompatActivity implements View.OnClickListener {
25
26
private Button fetchRoute;
27
private Button startNav;
28
private TextView routeGeometry;
29
private DirectionsRoute directionsRoute;
30
private List<DirectionsRoute> directionsRoutes;
31
private ProgressBar progress;
32
@Override
33
protected void onCreate(Bundle savedInstanceState) {
34
super.onCreate(savedInstanceState);
35
setContentView(R.layout.activity_custom_navigation);
36
fetchRoute = findViewById(R.id.fetchRoute);
37
startNav = findViewById(R.id.startNav);
38
routeGeometry = findViewById(R.id.routeGeometry);
39
progress = findViewById(R.id.progress);
40
fetchRoute.setOnClickListener(this);
41
startNav.setOnClickListener(this);
42
startNav.setEnabled(false);
43
44
}
45
46
@Override
47
public void onClick(View view) {
48
if (view.getId() == R.id.fetchRoute) {
49
progress.setVisibility(View.VISIBLE);
50
Point origin = Point.fromLngLat(103.75986708439264, 1.312533169133601);
51
Point destination = Point.fromLngLat(103.77982271935586, 1.310473772283314);
52
53
RouteRequestParams.Builder builder = RouteRequestParams.builder()
54
.origin(origin)
55
.destination(destination)
56
.language("en")
57
.departureTime((int) (System.currentTimeMillis()/1000));
58
59
RouteFetcher.getRoute(builder.build(), new Callback<DirectionsResponse>() {
60
@Override
61
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
62
progress.setVisibility(View.GONE);
63
//start navigation with the route we just fetched.
64
if (response.body() != null && !response.body().routes().isEmpty()) {
65
directionsRoute = response.body().routes().get(0);
66
directionsRoutes = response.body().routes();
67
routeGeometry.setText(String.format("Route Geometry: %s", directionsRoute.geometry()));
68
startNav.setEnabled(true);
69
}
70
}
71
72
@Override
73
public void onFailure(Call<DirectionsResponse> call, Throwable t) {
74
progress.setVisibility(View.GONE);
75
}
76
});
77
} else if (view.getId() == R.id.startNav) {
78
Intent intent = new Intent(this, NavigationViewActivity.class);
79
intent.putExtra("route", directionsRoute);
80
intent.putExtra("routes", (Serializable) directionsRoutes);
81
startActivity(intent);
82
}
83
}
84
}

NavigationViewActivity view source

1
package ai.nextbillion.navigation.demo.activity;
2
3
import android.Manifest;
4
import android.os.Build;
5
import android.os.Bundle;
6
import android.view.WindowInsets;
7
8
import java.util.List;
9
10
import ai.nextbillion.kits.directions.models.DirectionsRoute;
11
import ai.nextbillion.maps.location.modes.RenderMode;
12
import ai.nextbillion.navigation.core.navigation.NavEngineConfig;
13
import ai.nextbillion.navigation.demo.R;
14
import ai.nextbillion.navigation.ui.NavViewConfig;
15
import ai.nextbillion.navigation.ui.NavigationView;
16
import ai.nextbillion.navigation.ui.OnNavigationReadyCallback;
17
import ai.nextbillion.navigation.ui.listeners.NavigationListener;
18
import ai.nextbillion.navigation.ui.utils.StatusBarUtils;
19
import androidx.annotation.NonNull;
20
import androidx.appcompat.app.AppCompatActivity;
21
import pub.devrel.easypermissions.EasyPermissions;
22
import pub.devrel.easypermissions.PermissionRequest;
23
24
public class NavigationViewActivity extends AppCompatActivity implements OnNavigationReadyCallback, EasyPermissions.PermissionCallbacks, NavigationListener, StatusBarUtils.OnWindowInsetsChange {
25
26
NavigationView navigationView;
27
28
private String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
29
30
@Override
31
protected void onCreate(Bundle savedInstanceState) {
32
setTheme(ai.nextbillion.navigation.ui.R.style.Theme_AppCompat_NoActionBar);
33
34
super.onCreate(savedInstanceState);
35
setContentView(R.layout.activity_navigation_view);
36
37
navigationView = findViewById(R.id.navigation_view);
38
navigationView.onCreate(savedInstanceState);
39
StatusBarUtils.transparentStatusBar(this,this);
40
if (navigationView.isNightTheme()) {
41
StatusBarUtils.setDarkMode(this);
42
} else {
43
StatusBarUtils.setLightMode(this);
44
}
45
46
requestPermissions();
47
}
48
49
@Override
50
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
51
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
52
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
53
}
54
55
private void requestPermissions() {
56
EasyPermissions.requestPermissions(new PermissionRequest.Builder(this, 200, permissions)
57
.setRationale("Navigation requires location access")
58
.setNegativeButtonText("No")
59
.setPositiveButtonText("OK")
60
.build());
61
}
62
63
@Override
64
public void onNavigationReady(boolean b) {
65
NavEngineConfig.Builder navConfig = NavEngineConfig.builder();
66
NavViewConfig.Builder viewConfigBuilder = NavViewConfig.builder();
67
viewConfigBuilder.navigationListener(this);
68
69
configRoute(viewConfigBuilder);
70
viewConfigBuilder.shouldSimulateRoute(true);
71
viewConfigBuilder.showSpeedometer(true);
72
viewConfigBuilder.locationLayerRenderMode(RenderMode.GPS);
73
viewConfigBuilder.navConfig(navConfig.build());
74
75
navigationView.startNavigation(viewConfigBuilder.build());
76
}
77
78
private void configRoute(NavViewConfig.Builder viewConfigBuilder) {
79
DirectionsRoute route = (DirectionsRoute) getIntent().getSerializableExtra("route");
80
List<DirectionsRoute> routes = (List<DirectionsRoute>) getIntent().getSerializableExtra("routes");
81
viewConfigBuilder.route(route);
82
viewConfigBuilder.routes(routes);
83
}
84
85
86
@Override
87
public void onStart() {
88
super.onStart();
89
navigationView.onStart();
90
}
91
92
@Override
93
public void onResume() {
94
super.onResume();
95
navigationView.onResume();
96
}
97
98
@Override
99
public void onLowMemory() {
100
super.onLowMemory();
101
navigationView.onLowMemory();
102
}
103
104
@Override
105
public void onBackPressed() {
106
// If the navigation view didn't need to do anything, call super
107
if (!navigationView.onBackPressed()) {
108
super.onBackPressed();
109
}
110
}
111
112
@Override
113
protected void onSaveInstanceState(Bundle outState) {
114
navigationView.onSaveInstanceState(outState);
115
super.onSaveInstanceState(outState);
116
}
117
118
@Override
119
protected void onRestoreInstanceState(Bundle savedInstanceState) {
120
super.onRestoreInstanceState(savedInstanceState);
121
navigationView.onRestoreInstanceState(savedInstanceState);
122
}
123
124
@Override
125
public void onPause() {
126
super.onPause();
127
navigationView.onPause();
128
}
129
130
@Override
131
public void onStop() {
132
super.onStop();
133
navigationView.onStop();
134
}
135
136
@Override
137
protected void onDestroy() {
138
super.onDestroy();
139
navigationView.onDestroy();
140
}
141
142
@Override
143
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
144
navigationView.initialize(this);
145
146
}
147
148
@Override
149
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
150
151
}
152
153
@Override
154
public void onCancelNavigation() {
155
finish();
156
}
157
158
@Override
159
public void onNavigationFinished() {
160
161
}
162
163
@Override
164
public void onNavigationRunning() {
165
166
}
167
168
@Override
169
public void onApplyWindowInsets(WindowInsets windowInsets) {
170
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
171
navigationView.fitSystemWindow(windowInsets);
172
}
173
}
174
}

Code summary

This code example shows how to customize the NavigationView and launch it

  • The code provided an AppCompatActivity called NavigationViewActivity that demonstrates the usage of the NavigationView class for navigation purposes.

  • The onCreate() method is overridden to set up the activity layout and initialize the NavigationView

    • StatusBarUtils.transparentStatusBar(this,this): sets the status bar to be transparent

    • StatusBarUtils.setLightMode/DarkMode(this); set the status bar text and icons to be displayed in light/dark color, making them visible against the light/dark background.

  • The requestPermissions() method is called to request location permissions.

    • The onRequestPermissionsResult() method handles the result of the permission request.

    • navigationView.initialize(this) was called after the location permission was granted. The onNavigationReady() method is implemented from the OnNavigationReadyCallback interface, which is called when the navigation is ready to start.

  • The configRoute() method is used to configure the navigation route by extracting route information from the intent extras.

    • Various configuration options are set using NavViewConfig.Builder, such as enabling route simulation, showing a speedometer, setting the location layer render mode, and providing the navigation configuration.

    • The startNavigation() method is called on the NavigationView instance to begin the navigation.

  • Lifecycle methods (onStart(), onResume(), onLowMemory(), etc.) are overridden to forward the calls to the NavigationView instance.

    • The onBackPressed() method is overridden to handle the back button press and allows the NavigationView to handle it if necessary.

    • Methods for handling instance state, permissions granted/denied, navigation callbacks, and window insets are implemented.

    • The activity's lifecycle methods (onSaveInstanceState(), onRestoreInstanceState(), etc.) are overridden to propagate the corresponding calls to the NavigationView.

    • the activity is destroyed by calling onDestroy() on the NavigationView.

© 2024 NextBillion.ai all rights reserved.