Useful notes for developing with Kotlin Multiplatform + Jetpack Compose
2024-07-27
Since I'm working rather intensely with Kotlin Multiplatform for my current project BotvacCenter including all its benefits and drawbacks, I have accumulated quite some valuable knowledge about it as well its underlying Jetpack Compose UI framework. Thus, I want to share some of the knowledge I have struggled to find resources about with you in this post. It's rather a gathering of small notes than a continuous article, but hopefully still somewhat useful to someone out there...
Cross-platform settings
Almost any application needs to store some settings like username, encrypted password et cetera, but the
implementations of settings storage is often platform dependent, which makes it an unnecessary hustle
when working with a multiplatform project. Thankfully, the accordingly named
Multiplatform Settings
library exists, which implements a common way of persisting key-value data aka settings. By default, you
have to still write some platform-specific code to get it working, but the author was so kind to also
develop the
no-arg
module, which takes care of everything platform-specific and allows you to write your entire settings
logic in
commonMain
. Simply include the correct dependency described in the
README
and get started with the
easy-to-use API
. Personally, I like to develop a custom settings controller for all my project to handle reading and
writing my application's settings, but this library makes it so easy that it almost becomes unnecessary
boilerplate code - nice.
Install and use debug + release builds alongside each other
When developing a new feature for an already mature application, it can be really handy to run the current debug build you're working on alongside a stable release version. Even cooler, you can easily expand this concept of differentiating the debug from the release version to the displayed app name and icon. Here's how to do it:
-
Go into your
build.gradle.kts
and create adebug
variant underbuildTypes
. -
Then add
applicationIdSuffix = ".debug"
to this new variant in order to give debug builds a different application ID and thus allow them to coexist with release builds. You can change the suffix to anything you like. -
To customize your application name and icon, create the folders
src/androidRelease
andsrc/androidDebug
alongside your existingsrc/androidMain
to store the specific icon and app name for both build variants. -
Simply copy your existing resources folder
res
fromandroidMain
over toandroidRelease
to get started and make sure that you only include the relevant folders for the icon (drawable
and variousmipmap
folders) as well as thevalues/strings.xml
file storing your application name. -
Then use the
New/Image Asset
dialog to add your modified debug icon toandroidDebug
, copy overvalues/strings.xml
and change theapp_name
attribute to your desired debug app name. - Now release and debug variants should produce differently named applications with different icons.
Dropdown and time picker
For some stupid reason Kotlin Multiplatform still doesn't include stable dropdown or time picker UI components, which forces you to build your own solution. I don't want to praise my implementation as superior to anything else, but feel free to have a look at my dropdown and time picker components, that are surprisingly simple and haven't let me down.
Dark mode
Last but certainly not least I want to share a dark mystery with you - I'm talking about implementing
dark mode with Kotlin Multiplatform, which is something I failed miserably at multiple times, before
finally succeeding with a simple trick. You are most likely also wrapping the
MaterialTheme
composable around your actual UI code to give it the desired material styling. It also offers a
colors
attribute, which should turn the application into dark mode when setting it to the provided
darkColors()
palette. However, you will find that on desktop your application background still is white making
everything poorly legible, while on mobile everything looks good except for the loading screen still
being white. After lots of experimenting, here's the surprisingly simple solution to both of these
issues:
-
Simply wrap your UI code in a
Surface
composable to get the dark background on desktop resulting in this hierachyMaterialTheme > Surface > Your UI code
. -
Go into
AndroidManifest.xml
and change theandroid:theme
attribute to@android:style/Theme.Black.NoTitleBar
.
With that said, I have presented my most precious discoveries about Kotlin Multiplatform + Jetpack Compose to you. Some of them aren't perfect for sure, but they have worked reliably for me so far and that validates their existance in my mind, even if they are ugly. As always, feel free to share your thoughts in the comments down below and have a lovely day...