Android Studio Compose Multiplatform Development from Scratch

Author

Reads 1.2K

Stock Market Trading App with Graph Analysis
Credit: pexels.com, Stock Market Trading App with Graph Analysis

Android Studio Compose Multiplatform Development from Scratch is a powerful tool that allows developers to create native mobile apps for both Android and iOS using a single codebase. This approach is especially useful for cross-platform development, where you can share code between platforms.

One of the key benefits of using Android Studio Compose for multiplatform development is that it enables you to write UI code in Kotlin, which is a concise and expressive language. By using Compose, you can create complex UI layouts with ease, without having to worry about the underlying platform specifics.

To get started with Android Studio Compose multiplatform development, you'll need to set up a new project in Android Studio. This involves creating a new project, selecting the Compose multiplatform template, and configuring your project settings.

In the next section, we'll dive deeper into the process of setting up a new project and configuring your Compose multiplatform settings.

Getting Started

A Close-Up Shot of Children Getting Jars of Paint
Credit: pexels.com, A Close-Up Shot of Children Getting Jars of Paint

First, make sure you have the latest version of Android Studio installed on your computer.

Android Studio Compose Multiplatform is built on top of the Kotlin programming language, which is a key feature of the Android Jetpack Compose framework.

To create a new Compose project, navigate to File > New > New Project in Android Studio, and select the "Compose UI" template.

Compose Multiplatform is designed to work seamlessly with the existing Compose UI library, allowing you to share code between Android and iOS.

This means you can write a single Compose UI component and deploy it across multiple platforms with minimal modifications.

The official Compose Multiplatform sample project, available on GitHub, provides a great starting point for exploring the capabilities of this technology.

Recommended read: Nextcloud Docker-compose

Adding Platform-Specific Code

When adding platform-specific code, you'll often encounter situations where you need to create separate implementations for different platforms.

You can use the expect keyword in a file like CustomDropdown.kt in the commonMain directory to declare the platform-specific code that will be implemented later. This is a common pattern when you're dealing with platform-specific requirements.

For example, you might create separate files like DesktopCustomDropdown.kt in the desktopMain directory to implement the platform-specific code for desktop. Remember, these implementations are separate and not identical, even if they look similar.

Add Platform-Specific Composable

Credit: youtube.com, How to add platform-specific icons to a Compose Multiplatform project

When you need to add platform-specific code for a composable, you can create a common composable in the commonMain directory.

In the commonMain directory, create a file for the common composable, such as CustomDropdown.kt. Inside this file, use the expect keyword.

You'll also need to create platform-specific code for each platform, such as desktop and Android. For example, in desktopMain, you can create a file called DesktopCustomDropdown.kt.

These platform-specific composables, like DesktopCustomDropdown.kt, are separate implementations and are not the same as the common composable.

After creating these files, you can use the common composable CustomDropdownMenu() in the commonMain directory.

Common Dependencies and Platform-Specific Code

When working on a multiplatform project, you'll often find yourself dealing with libraries that don't have a single common dependency. This is where things get interesting.

Some libraries, like mockk, require adding platform-specific dependencies next to the common one. In a multiplatform project that uses mockk, you should add the following dependencies in the common module build.gradle.kts:

Credit: youtube.com, How to Manage Platform-Specific Dependencies in Maven and Gradle

You need to keep this in mind when deciding to use a new library in your multiplatform project. This will save you a lot of headaches down the line.

In addition to libraries, you'll also need to consider platform-specific code. This can be a challenge, especially when it comes to user interface elements like dropdown menus.

To create a common composable for a dropdown menu, you can create a CustomDropdown.kt file in the commonMain directory. Inside it, use the expect keyword.

This will allow you to use a common composable CustomDropdownMenu() in the commonMain directory, while still having platform-specific implementations for each platform.

Declaring Dependencies

Declaring dependencies is a crucial part of setting up an Android Studio Compose multiplatform project. You can hold a single source of truth for dependencies by using Kotlin objects from buildSrc or Gradle version catalogues.

In a multiplatform project, it's essential to keep track of your dependencies, especially when using libraries that don't have a single common dependency. Libraries like mockk require platform-specific implementations, so you'll need to add those dependencies next to the common one in the common module build.gradle.kts file.

To use a new library in your project, remember to add the necessary platform-specific dependencies in the common module build.gradle.kts file, as you would with mockk.

Purpose of Modules

A music producer uses a synthesizer and laptop for composing in a home studio.
Credit: pexels.com, A music producer uses a synthesizer and laptop for composing in a home studio.

Modules serve as entry points to the application, with platform-specific modules referencing a common module where you can put common code like Compose Multiplatform composables, domain, and data code.

The common module is where you'll put most of the multiplatform code, specifically in the commonMain directory.

Declaring Dependencies

You can hold a single source of truth for dependencies in a multiplatform project, just like in a regular multimodule Android application. This means you can use Kotlin objects from buildSrc or Gradle version catalogues if you prefer.

You can opt in to use Kotlin objects from buildSrc in your multiplatform project. This is a viable option for managing dependencies.

In a multiplatform project, you can also use Gradle version catalogues to manage dependencies. This is another option worth considering.

To use a new library in your multiplatform project, you should keep in mind that some libraries, like mockk, require platform-specific dependencies in addition to the common one. This is something to be aware of when deciding to use a new library.

You need to add platform-specific dependencies next to the common one in the common module build.gradle.kts for libraries like mockk. This is a necessary step.

For another approach, see: How to Use Google Drive for Android

Implementing Screens

Credit: youtube.com, Deep Link Navigation in Android with Jetpack Compose | Kotlin Multiplatform | Compose Multiplatform

Implementing screens is a crucial step in building an Android Studio Compose Multiplatform app. You can start by creating a new screen, like ScreenHome, which implements the Screen interface.

To implement the ScreenHome, you'll need to modify the App.kt file. This is where you'll put the code for the content composable that will be displayed on the screen.

Add TopAppBar

Adding a TopAppBar is a great way to give your app a professional look and provide easy access to navigation and actions. You can add a TopAppBar to your app by following a few simple steps.

In our example, we added a TopAppBar to App.kt as shown below. This is a crucial step in implementing screens for your app.

In the example, we mentioned that we may add a TopAppBar to App.kt as below - this shows that it's an optional step, but one that can greatly enhance the user experience. The TopAppBar is a key feature in providing a clean and intuitive interface for your app.

Credit: youtube.com, Top App Bar (Toolbar) - UX With Material3

To implement the TopAppBar, we followed a specific set of steps, including adding the necessary code to App.kt. This code is essential in bringing the TopAppBar to life and making it functional for your users.

By adding a TopAppBar, you can provide your users with a clear and consistent navigation experience, which is essential for any app.

Step 3: Implement ScreenHome

Now that we've set up our app, it's time to implement the ScreenHome. We'll be working with the Screen interface, which is a crucial part of our app's structure.

We need to implement the ScreenHome, which will use the Content composable. This is where things get interesting, as we'll be modifying the App.kt file to include our new screen.

The ScreenHome will be a key part of our app, providing a home screen for users to interact with. To implement it, we'll need to follow the instructions provided.

The instructions tell us to modify the App.kt file, which will involve implementing the ScreenHome. This is a critical step in bringing our app to life.

Sharing Strings

Credit: youtube.com, How to Successfully Share a List String Between Screens in Jetpack Compose Using ViewModel

Sharing strings across different screens is a crucial aspect of implementing screens. You can use the moko-resources library to share strings across all platforms. This library makes it easy to share strings between screens.

In order to share strings, you'll need to modify your screens to accept the shared strings as values. For example, you can modify ScreenDetail to accept the textString argument as a value in the screen.

To pass the shared strings between screens, you can pass the textString argument from one screen to another, as demonstrated in the example of passing arguments between screens. This involves modifying the screens to accept and pass the shared strings.

Migrate Android UI Code

Migrating your Android UI code to multiplatform involves moving directories and files to their respective places in the project structure.

Start by moving all the directories inside androidApp/ui into shared-ui/commonMain/ui. Don't move the MainActivity.kt file, since activities are Android-specific.

Credit: youtube.com, Multi-language Support in Kotlin/Compose Multiplatform - Android/iOS

To successfully migrate your code, you'll need to create a new directory structure within the shared-ui module. This includes creating a new directory called commonMain, which will hold all multiplatform dependencies and code that works across all declared platforms.

In the commonMain directory, you'll want to add the necessary dependencies for your multiplatform project. These include Compose and other module dependencies, which you can add using the following command: "Add blow plugins in project and all module level build.gradle."

When adding dependencies, make sure to check if they support all platforms you've defined in your Gradle file. This includes platforms like Android, iOS, and JVM.

Here's a simple table to help you visualize the new directory structure:

By following these steps and creating a new directory structure, you'll be well on your way to migrating your Android UI code to multiplatform.

Handling Navigation and Images

Handling Navigation and Images is a breeze with the precompose library. It efficiently handles navigation between different screens, allowing users to seamlessly switch between tabs on the bottom navigation bar.

The precompose library also makes it easy to handle images, but that's a topic for another section.

The library's ability to handle navigation is particularly useful in the learn feature, where users can easily switch between tabs.

Add Navigation Animation

Close-up of a smartphone displaying an app interface with a blurred bokeh background for a modern tech feel.
Credit: pexels.com, Close-up of a smartphone displaying an app interface with a blurred bokeh background for a modern tech feel.

Adding navigation animation to your app can make it more engaging and user-friendly.

You can add a navigation transition animation by implementing SlideTransition in the Navigator lambda, which takes navigator as a parameter. This is done by adding a specific line of code as shown in the example.

To implement SlideTransition, you need to add a specific line of code that includes the Navigator lambda. This is a crucial step in creating a smooth navigation experience for your app's users.

Handling Navigation

Handling navigation between different screens is a breeze with the precompose library. It allows users to change between tabs on the bottom navigation bar.

The library also handles navigation transitions with ease. To add a navigation transition animation, you can implement SlideTransition in the Navigator lambda which takes navigator as a parameter.

Passing arguments between screens is a straightforward process. To do this, you can modify the screen to accept the textString argument as a value, as shown in the example of modifying ScreenDetail to accept the textString argument.

By passing the textString argument to the next screen, you can easily share data between screens.

Fetching Images

Credit: youtube.com, ChatEdit: Navigation

Fetching images in your app is a crucial task, and it's about to get a lot easier. You'll be migrating from Coil to Compose ImageLoader, which is a more suitable choice for Multiplatform.

Compose ImageLoader is a great option because it's designed to work seamlessly across different platforms. Unfortunately, Coil doesn't fully support Multiplatform, so this change is necessary.

To load local images, you'll need to write custom logic in Kotlin Multiplatform. This is because Android uses the R class to reference images, which doesn't exist on other platforms.

Customizing UI

Customizing UI is where the magic happens. You get to tailor your app to fit your unique style and needs. To start, you'll want to configure custom fonts for your app, which can be done using moko-resources to load new fonts. OpenSans is a great font to use, but you'll need to set it as the default font for each platform.

Using moko-resources will help you load the new font, making it easy to implement across your app. This is especially useful when working with multiple platforms.

Using Third-Party Libraries

Credit: youtube.com, Flight Booking App - Part 0 | Project Setup ( compose Multiplatform + GitHub)

As you're working with Android Studio Compose Multiplatform, you'll be happy to know that a community-driven library ecosystem is emerging to help bridge the gap between Android and desktop apps.

Compose Multiplatform is still in its early stages, but the community is already releasing libraries to make development easier.

You can tap into this growing library ecosystem to simplify your development process and focus on building your app.

One of the libraries you can use is the one that helps make the bridge between Android and desktop apps, as mentioned in your project instructions.

With the help of these libraries, you'll be able to streamline your development workflow and create more complex and engaging user interfaces.

To get started, open your desktopApp project and look for the instructions on how to use these libraries effectively.

Background and Why

Jetpack Compose offers a declarative API, which is a significant advantage over traditional XML layouts. This flexibility makes migration to Compose Multiplatform relatively easy.

The main advantage of using Jetpack Compose is its flexibility, allowing for smoother codebase unification. This is especially beneficial for businesses that want to unify their codebase without significant disruption.

Compose Multiplatform makes it easier to unify the codebase step by step without the need for additional developers.

Background

A young musician composing music indoors, focused on playing the keyboard in a cozy room.
Credit: pexels.com, A young musician composing music indoors, focused on playing the keyboard in a cozy room.

Kotlin Multiplatform comes in many flavors, as seen in the template gallery.

The Shared UI Multiplatform App using Compose Multiplatform is a popular choice for building cross-platform apps.

We'll be using this approach for the Lithium CRM app, following the guide provided by JetBrains.

This approach allows for a shared codebase across multiple platforms, which can simplify development and maintenance.

The guide to creating a first app using Compose Multiplatform is available on the JetBrains website.

Why

Jetpack Compose offers a lot of flexibility, which is a major advantage over traditional XML layouts. This flexibility makes it easier to migrate to Compose Multiplatform.

Some developers describe Jetpack Compose as a declarative API, but its flexibility is what really sets it apart.

Migration Process

To start migrating your Android UI code to multiplatform, you'll want to move all directories inside `androidApp/ui` into `shared-ui/commonMain/ui`, leaving the `MainActivity.kt` file behind since activities are Android-specific.

Create a KMP module in your codebase and move your code iteratively to `commonMain`.

Credit: youtube.com, How to Migrate Jetpack Compose App to Compose Multiplatform. Add iOS Support In Jetpack Compose App

You'll also need to create connectors for parts that can't be moved away from the platform, such as Retrofit to Ktor and Glide to Coil 3.

The process is a bit different when using an automated CI/CD pipeline, but that's a story for another time.

Here's a step-by-step guide to getting started:

  1. Create a KMP module in your codebase.
  2. Move your code iteratively to `commonMain`.
  3. Make connectors for parts that can't be moved away from the platform.

With sourSets, you can define all platform-specific dependencies, such as `wasm` for browser applications, `androidTarget` for Android applications, and `iosXXX` for iOS applications.

You'll also need to add `compose` and `module` dependencies in `commonMain` and sync the project.

When moving files, be sure to copy all code written with any multiplatform library into `commonMain`, and move resources and assets to the corresponding platform-specific directories.

The current setup will only work for Android targets, so you'll need to enable other platform targets as well, such as iOS, Desktop, and Web.

To do this, use the "Kotlin Multiplatform Wizard" to create a sample with all required targets, and try running all targets to see the output.

Bessie Fanetti

Senior Writer

Bessie Fanetti is an avid traveler and food enthusiast, with a passion for exploring new cultures and cuisines. She has visited over 25 countries and counting, always on the lookout for hidden gems and local favorites. In addition to her love of travel, Bessie is also a seasoned marketer with over 20 years of experience in branding and advertising.

Love What You Read? Stay Updated!

Join our community for insights, tips, and more.