Modern Android Development Unleashed: Jetpack Compose, Kotlin, and Beyond

Practical knowledge from a Seven Peaks Speaks Android Meetup


In the recent Seven Peaks Speaks Android meetup, three talented Android developers explored the composable future of modern Android development and the transformative advancements that will reshape the way developers design elegant, efficient, and high-performance user interfaces.

This article provides a comprehensive summary of the invaluable insights shared by the speakers: Fedor Erofeev, Senior Android Developer at Seven Peaks Software; Muhammad Naeem, Senior Android Developer; and Tipatai Puthanukunkit, Junior Principal Engineer at MuvMi.

Together, they explored groundbreaking innovations in the Android ecosystem, including Jetpack Compose, efficient Kotlin constructions, user-friendly APIs, and a robust toolkit featuring Material Design, Dark Theme, and animation support—all aimed at streamlining and accelerating Android development.

Read on to discover the key takeaways and expert opinions from this insightful meetup that shed light on the future of Android development.

1. Navigate easily between screens with Jetpack Compose

Android developer

In the first talk, Fedor Erofeev guided the audience through the process of setting up navigation with Jetpack Compose. This summary covers the following topics:

  1. Setting up dependencies
  2. Creating a navigation host
  3. Adding composable destinations
  4. Passing data between screens
  5. Implementing deep links
  6. Testing navigation
  7. Adding screen transitions

1. Setting up dependencies

To start, add the necessary dependencies to your project:

  • Navigation Compose: Required for setting up a navigation host and passing simple data between screens.
  • Serialization Library: Required if you plan to pass parcelable data between screens. Use the Kotlin Serialization Library.
  • Navigation Testing Library: Required for testing navigation.
  • Google Accompanist Library: Required for animating screen transitions.

2. Creating a navigation host

To create a navigation host, call the navigationHost() function with the following parameters:

  1. navController: Use rememberNavController() from the library.
  2. startDestination: Define your starting destination (e.g., “Splash”).
  3. builder: Access the NavigationGraphBuilder.

3. Adding composable destinations

To add composable destinations to the navigation host, use the composable() function with the following parameters:

  1. route: Define the route (e.g., “SplashScreen”).
  2. content: Call your screen-level composables.


You also have access to the navBackStackEntry for retrieving arguments.

4. Passing data between screens

Jetpack Compose recommends passing only primitive data between screens. Out of the box, Compose navigation offers 11 types, including booleans, floats, integers, longs, strings, and arrays of these types.

To pass data:

  1. Define the route with the argument inside curly braces (e.g., “SimpleArguments/{argument}”).
  2. Provide a list of named NavArgument with the same name as the argument in the route and set its type.
  3. Use the navBackStackEntry to get the argument and pass it to your screen.


If you need to pass Parcelable data, create a custom NavType that extends NavType with your Parcelable data class. Override the get(), parseValue(), and put() methods.

5. Implementing deep links

Implementing deep links with Jetpack Compose is easy. First, declare an intent-filter for your deep link in the AndroidManifest.xml. Next, add a deepLinks parameter to the composable() function and provide a list of NavDeepLink.

6. Testing navigation

To test navigation, set up a ComposeTestRule, create a TestNavHostController, and pass it to your navigation class. Then, use the ComposeTestRule to perform actions and assert the correct destination route.

7. Adding screen transitions

To add screen transitions using the Google Accompanist Library, follow these steps:

  1. Replace navController with rememberAnimatedNavController().
  2. Replace navigationHost with animatedNavigationHost.
  3. Replace the import for the composable() function with the one from the Accompanist Library.
  4. Define the entry, exit, pop entry, and pop exit transitions in the animatedNavigationHost.


You can also define individual transitions for each destination using the same set of parameters in the composable() function.

With these steps, you can easily add navigation, pass data between screens, implement deep links, test navigation, and add beautiful screen transitions to your Jetpack Compose application.

Presentation Slides:

2. Jetpack Compose animation: revolutionizing Android development

Android Developer

In the second talk, Muhammad Naeem spoke about implementing animations in mobile applications using the Jetpack Compose Animation library.

To provide a comprehensive understanding of the available animation capabilities, this summary is divided into two sections: high-level API and low-level API.

High-level API

The high-level API consists of three core components: animating visibility, content size, and cross-fade. With Jetpack Compose, you no longer need to create separate XML files to define animations; instead, the library automatically provides default animations for entering and exiting, including fading, scaling, and sliding.

Animating visibility

To make content appear or disappear based on user interaction, use the animatedVisibility function. You can define the visibility transition using predefined animations like fadeIn, fadeOut, and slideIn or slideOut.

Content size animation

Content size animation allows you to change the content displayed on the screen based on user interaction. For instance, when a user clicks on a button, the content may change or expand to reveal more information.

Cross-fade animation

Cross-fade animation smoothly transitions between two composables, allowing content to appear and disappear seamlessly.

Low-level API

The low-level API is the foundation for the high-level API and consists of three primary components: Animatable, AnimateAsState, and Animation.


Animatable holds the value of an animatable property during a transition. It is used for transitioning between screens or states.


AnimateAsState is a composable function that allows you to animate a value based on a provided target state. It can be used to create animations such as changing button size, color, or position.


Animations in Jetpack Compose can be divided into two types: target-based animation and decay animation.

  • Target-based animation requires the initialization of a starting value and a target value. You can define the duration of the animation and the easing function to control the speed of the transition.
  • Decay animation does not require a starting value and is typically used for touch gestures. It provides a more natural feel to the animation by slowing down as it approaches the target value.


Custom animations with AnimationSpec

To create custom animations, you can use the AnimationSpec class. It offers several predefined animation types, such as Tween, Spring, Keyframe, Repeatable, InfiniteRepeatable, and Snap. These can be combined or modified to create unique animations tailored to your application.

Previewing and testing animations

To preview and test your animations in Android Studio, locate the animation icon in the XML preview. Clicking the icon allows you to play the animation, adjust the speed, and examine the animation properties.


Jetpack Compose Animation library simplifies the process of implementing animations in mobile applications. With its high-level and low-level APIs, developers can create complex animations with ease, resulting in a more engaging user experience.

Presentation Slides:

Would you like to develop Android apps at Seven Peaks?

See our career opportunities

3. Compose screenshot testing made easy

android developer

In the third talk of the meetup, Tipatai Puthanukunkit explained how to enhance Android UI testing using Compose Shot and Showkase. He focused on simplifying and automating component consistency, making it easier to maintain high-quality user interfaces. The following is a summary of his talk.

What is SketchUp testing?

SketchUp testing consists of two steps:

  1. Record: Capture the screen as an image and save it in storage.
  2. Verify: Run the test again, comparing the current screen with the saved screenshot to see if the differences are acceptable.


Advantages of SketchUp testing include the simplicity and speed of capturing and verifying UI states. However, it lacks the ability to test user interactions like navigation flow.


Available libraries include:

  1. SHOT: A library for running screenshot tests on real devices or emulators. We will not use this library in this tutorial.
  2. Paparazzi: A more efficient alternative to SHOT that does not require real devices or emulators. It exports Android Studio’s render engine for screenshot tests.
  3. Showkase: A library that detects and generates metadata for all Composable previews in the project, allowing for easier testing.
  4. Test Parameter Injectors: A library from Google that transforms Showkase metadata into unit test cases.


Setting up Paparazzi

To set up Paparazzi, you need to restructure your project to separate UI components into separate modules. Paparazzi works with multi-module projects and can be set up to run on an Android library module only.

Using stateless composables

Stateless composables make it easier to create preview functions for different states. This is achieved by separating the state and the dispatch function on a composable screen. The state is rendered by the composable UI, and the dispatch function handles user interactions.

Creating preview functions

Using Compose, create multiple preview functions representing different UI states. These previews can be displayed simultaneously in the Android Studio IDE.

Integrating previews with Paparazzi

After creating the preview functions, integrate them into the Paparazzi test code. Call the record command to generate screenshots for each test case. The verify command can be used to check if the current composable matches the recorded image.

Automating test cases with Showkase and test parameter injectors

  1. Set up Showkase by creating a Showcase module and extending the ShowcaseRuleModule. Annotate it with the ShowcaseRule annotation.
  2. Define a PreviewProvider class to provide test parameters for the test cases. Integrate Showkase metadata with the Test Parameter Injector library.
  3. Annotate the Paparazzi test class with the RunWith TestParameterInjector annotation. Define a single test function with the TestParameter annotation, using the PreviewProvider as a value provider.



In this section, you have learned how to enhance Android UI testing using Compose Shot and Showkase. By integrating Paparazzi, Showkase, and Test Parameter Injectors, you can simplify and automate the process of maintaining component consistency in Android UI projects.

Presentation Slides:

Interested in joining the Seven Peaks development team? Visit our careers page now!

Sign up today & start getting tech news.

Get the latest tech trends directly in your inbox each month. And get invited to exclusive events.