Installing Enro

Add the Gradle Dependencies

The first step in installing Enro is to add the Gradle dependencies to your project. These should be added to your application module, as well as any modules that will use Enro.

Maven Central


dependencies {
    implementation("dev.enro:enro:<latest_version>")
    ksp("dev.enro:enro-processor:<latest_version>") // optional but highly recommended
    // kapt("dev.enro:enro-processor:<latest_version>") - if you're using KAPT not KSP
    testImplementation("dev.enro:enro-test:<latest_version>") // optional test extensions
}

Add Enro to your Application class

Enro needs to be added to the Application class used by your Application. This is also where you can apply custom configuration to Enro, if your application requires this.

Show step-by-step guide

0. An application class without Enro installed


class ExampleApplication : Application {
    // ...
}

1. Add the NavigationApplication interface


class ExampleApplication : Application, NavigationApplication {
    // ...
}

2. Override the navigationController property


class ExampleApplication : Application, NavigationApplication {
    override val navigationController = createNavigationController { }

    // ...
}

In the example above we’re passing an empty block to the createNavigationController function, but this block is used to provide configuration to Enro. In a simple application that uses annotation processing, you may not need to provide any configuration, but it’s useful to be aware that this is what the block is used for. Please see Configuring Enro for more information.

3. Add the @NavigationComponent annotation to your Application (if using kapt/annotation processing)


@NavigationComponent
class ExampleApplication : Application, NavigationApplication {
    override val navigationController = createNavigationController { }
    
    // ...
}

If you are using annotation processing (which is optional, but recommended), you are required to annotate your Application class with @NavigationComponent so that the annotation processor has a hook to generate and provide configuration.

If you are not using annotation processing, you won’t need to add this annotation. Instead, you’ll need to provide your Application’s configuration within the createNavigationController block. Please see Configuring Enro for more information.

Add Enro to an Activity

Once you’ve added Enro to your Application, it’s likely that you’ll want to add a Navigation Container to an Activity. This isn’t necessary, as navigation using Enro will work even without a Navigation Container, but it is recommended. The exact configuration of the Navigation Container will depend on your needs, and the examples below will deal with a reasonably simple case, so if you need more information on how to configure a Navigation Container, please see the Navigation Container documentation.

What is a Navigation Container?

A Navigation Container is a ViewGroup or Composable that maintains a backstack and displays the active Navigation Destination for that backstack. If you’re familiar with Fragments, think of it as the FrameLayout that holds the Fragments. If you’re more familiar with Compose, think of it as a Box that holds some child content (the active destination). For more information, please see the Navigation Container documentation.

Adding a Navigation Container for Fragments and Composables

If your application has Navigation Destinations that are a mix of Fragments and Composables, your top level Navigation Container should be a View based Navigation Container, as this will accept both Fragment and Composable destinations.

Show step-by-step guide

0. An Activity without a Navigation Container


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

1. Add a FrameLayout to your Activity’s layout file


<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/exampleNavigationContainer"
        />
    <!-- ... -->
</androidx.constraintlayout.widget.ConstraintLayout>

2. Add a Navigation Container property to your Activity


class MainActivity : AppCompatActivity() {

    private val exampleContainer by navigationContainer(
        containerId = R.id.exampleNavigationContainer,
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

3. Configure the Navigation Container

The Navigation Container that we’ve defined above will start off with nothing in it, and it will allow any Navigation Destination to be pushed into it. Below is an example of a configured Navigation Container that will initially show the Navigation Destination for a particular Navigation Key, and will finish the Activity if the Navigation Container is ever about to become empty. This isn’t always the behavior that you will want for a Navigation Container, but it is a reasonably common way to set up an Activity’s root Navigation Container. For more information, please see the Navigation Container documentation.


class MainActivity : AppCompatActivity() {

    private val exampleContainer by navigationContainer(
        containerId = R.id.exampleNavigationContainer,
        root = { ExampleRootNavigationKey(/* ... */) }, 
        emptyBehavior = EmptyBehavior.CloseParent,
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Adding a Navigation Container for Composables only

If your application only has Composable destinations, you can choose to use a View based Navigation Container (as these support Composable destinations too), but you may want to consider directly using a Composable NavigationContainer.

Show step-by-step guide

0. A Composable Activity without a Navigation Container


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // ...
        }
    }
}

1. Add a Navigation Container variable


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val container = rememberNavigationContainer()
            // ...
        }
    }
}

2. Render the Navigation Container


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val container = rememberNavigationContainer()
            
            Box(modifier = Modifier.fillMaxSize()) {
                container.Render()
            }
            // ...
        }
    }
}

3. Configure the Navigation Container

The Navigation Container that we’ve defined above will start off with nothing in it, and it will allow any Navigation Destination to be pushed into it. Below is an example of a configured Navigation Container that will initially show the Navigation Destination for a particular Navigation Key, and will finish the Activity if the Navigation Container is ever about to become empty. This isn’t always the behavior that you will want for a Navigation Container, but it is a reasonably common way to set up an Activity’s root Navigation Container. For more information, please see the Navigation Container documentation.


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val container = rememberNavigationContainer(
                root = ExampleRootNavigationKey(/* ... */), 
                emptyBehavior = EmptyBehavior.CloseParent,
            )

            Box(modifier = Modifier.fillMaxSize()) {
                container.Render()
            }
            // ...
        }
    }
}