Using Maplibre with Jetpack Compose

Using Maplibre with Jetpack Compose

What is Jetpack Compose?

Jetpack Compose is a modern toolkit for building Android user interfaces using a declarative programming model. With Jetpack Compose, you can create UI components and layouts in a simple and intuitive way, using Kotlin code to define your app's user interface.

One of the key advantages of Jetpack Compose is that it allows you to write less code than with traditional Android UI frameworks. With Compose, you can build complex UIs with fewer lines of code, which can make your codebase more maintainable and easier to reason about.

Less Code

Writing less code affects all stages of development: as an author, you get to focus on the problem at hand, with less to test and debug and with less chances of bugs; as a reviewer or maintainer you have less code to read, understand, review and maintain. Compose allows you to do more with less code, compared to using the Android View system: Buttons, lists or animation - whatever you need to build, now there’s less code to write.


Compose uses a declarative API, which means that all you need to do is describe your UI - Compose takes care of the rest. With Compose, you build small, stateless components that are not tied to a specific activity or fragment. That makes them easy to reuse and test. In Compose, state is explicit and passed to the composable. That way there’s one single source of truth for the state, making it encapsulated and decoupled. Then, as app state changes, your UI automatically updates.

Accelerate Development

Compose is compatible with all your existing code: you can call Compose code from Views and Views from Compose. Most common libraries like Navigation, ViewModel and Kotlin coroutines work with Compose, so you can start adopting when and where you want. Using the full Android Studio support, with features like live previews, you get to iterate and ship code faster.


Compose enables you to create beautiful apps with direct access to the Android platform APIs and built-in support for Material Design, Dark theme, animations, and more. With Compose, bringing movement and life to your apps through animations is quick and easy to implement. Whether you’re building with Material Design or your own design system, Compose gives you the flexibility to implement the design you want.

What Challenges Do We Can Solve using Jetpack Compose?

When writing our code we create multiple methods for different purposes. After that we couple this method in our main function according to our requirement. In Android when building any type of view and setting data to that particular view. First of all, we initialize that view with a variable and then add data to that specific view. This process of coupling UI elements with the View Model is called Coupling. When our code is having so many couplings it becomes difficult to maintain this code. So coupling can give you sometimes some Null Reference errors.

While developing apps in Java we generally prefer using the View Modal concept in which we find each view from our XML layout file inside our Java class and add data to that specific view according to our requirement. In most apps, we use the UI elements to display dynamically so this may sometimes give you an error of NullReference. In this method, UI elements are declared in XML language whereas the functionality is written in java or Kotlin and we link UI elements with our Java or Kotlin class with the findViewbyId() method.

If we will prefer to use the same language for writing our UI components and for adding the functionality it will become easier to maintain our code. By using this method the number of couplings inside our code will also reduce.

fun PasswordField() {
var password by remember { mutableStateOf("") }
var isPasswordVisible by remember { mutableStateOf(false) }

val passwordIcon = if (isPasswordVisible) {
  painterResource(id = drawable.baseline_visibility_24)
} else {
  painterResource(id = drawable.baseline_visibility_off_24)

val passwordVisibilityTransformation = if (isPasswordVisible) {
} else {

  modifier = Modifier.fillMaxWidth(),
  value = password,
  onValueChange = { password = it },
  label = {
    Text(text = "Password")
  trailingIcon = {
    IconButton(onClick = { isPasswordVisible = !isPasswordVisible }) {
        painter = passwordIcon,
        contentDescription = "visible"
  visualTransformation = passwordVisibilityTransformation

Some Basic Functions of Jetpack Compose

Composable Function: Composable Function is represented in code by using @Composable annotation to the function name. This function will let you define your app’s UI programmatically by describing its shape and data dependencies rather than focusing on the UI construction process.
Preview Function: The name of the function itself tells us that the function is used to generate the preview of the composable function. It is used to display a preview of our composable functions within our IDE rather than installing our APK in an emulator or a physical device. The preview function is annotated by @Preview.
Column Function: The column function is used to stack UI elements in a vertical manner. This function will stack all the children directly one after another in a vertical manner with no spacing between them. It is annotated with Column().
Row Function: The row function is used to stack UI elements in a horizontal manner. This function will stack all the children one after the other in a horizontal manner with no spacing between them. It is annotated with Row().
Box: A widget that is used to position elements one over another. It will position its children relative to its edges. The stack is used to draw the children which will overlap in the order that they are specified. It is annotated with Box().
Spacer: It is used to give spacing between two views. We can specify the height and width of the box. It is an empty box that is used to give spacing between the views. It is annotated with Spacer().
Vertical Scroll: If the UI components inside the app do not fit the height of the screen then we have to use the scrolling type of view. With the help of a vertical scroller, we can provide a vertically scrolling behavior to our view. The contents inside the vertical scroller will be clipped to the bounds of the vertical scroller. It is annotated with VerticalScroll().
Padding: The padding function is used to provide extra white space according to the requirement around the specific view. It is simply annotated with Padding().
Lazy List: This composable is equivalent to a recycler view in android’s view system. It is annotated with LazyColumn().

Maplibre Integration in Android Jetpack Compose

MapLibre is an open-source mapping library that can be used in Android applications to display maps and provide location-based services. It is based on the Mapbox GL Native library and provides a similar set of features, but with the added benefit of being open source.

To use MapLibre in an Android application, developers can add the MapLibre GL Native library as a dependency in their project. This library provides a set of classes and interfaces that can be used to display maps, add markers and other map features, and interact with the map.

In this blog, we will discuss how to use MapLibre with Jetpack Compose in Android Kotlin.

To use MapLibre in Jetpack Compose, we first need to add the MapLibre dependency to our project. We can do this by adding the following line to our app's build.gradle file:

implementation ''

Next, we need to create a Composable function that will display the map. This can be done using the AndroidView function provided by Jetpack Compose. The AndroidView function allows us to embed an Android view into our Composable function.
Here is an example Composable function that displays a MapLibre map:

fun MapView() {
factory = { context ->
  Mapbox.getInstance(context, null)
  val mapView = MapView(context)
  val styleUrl = "";
  mapView.getMapAsync { map ->
    // Set the style after mapView was loaded
    map.setStyle(styleUrl) {
      map.uiSettings.setAttributionMargins(15, 0, 0, 15)
      // Set the map view center
      map.cameraPosition = Builder()
        .target(LatLng(28.679079, 77.069710))

In this example, we create a MapView object and set its style URL to the Mapbox Streets style. We then create a CameraPosition object and set the map's center coordinates, zoom and bearing level. Finally, we return the MapView object from the AndroidView function.
We can then use this Composable function in our app's UI like any other Composable function:

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
setContent {
    MapLibreJetpackComposeBlogTheme {
        // A surface container using the 'background' color from the theme
      modifier = Modifier.fillMaxSize(),
      color = MaterialTheme.colors.background
        ) {

And that's it! With just a few lines of code, we have integrated a MapLibre map into our Jetpack Compose app. We can now customize the map further by adding markers, overlays, and other features provided by MapLibre.

Adding and Customizing Marker

To add a MapLibre marker in Jetpack Compose for Android using Kotlin, you need to first create a MarkerOptions object and setting its position, title and snippet, In the getMapAsync callback.

  .position(LatLng(latitude, longitude))

Replace latitude and longitude with the coordinates of your desired location. Also replace markerTitle and markerSnippet with the desired title and snippet.
You can customize the marker's appearance by setting its icon in the MarkerOptions object.

        .position(LatLng(latitude, longitude))

Replace icon with the name of your desired marker icon resource file.