Explore composable code
Let's examine closely the sample composable created by the Kotlin Multiplatform wizard. First, there is the composable
App() function that implements the common UI and can be used on all platforms. Second, there is the platform-specific code that launches this UI on each platform.
Implementing composable functions
Take a look at the
App() function in
App() function is a regular Kotlin function annotated with
@Composable. These kinds of functions are referred to as composable functions or just composables. They are the building blocks of a UI based on Compose Multiplatform.
A composable function has the following general structure:
MaterialThemesets the look of the application. The default settings can be customized. For example, you can choose colors, shapes, and typography.
Columncomposable controls the layout of the application. Here, it displays a
Textcomposable, which renders some text.
AnimatedVisibilityshows and hides the
Imageusing an animation.
painterResourceloads a vector icon stored in an XML resource.
horizontalAlignment parameter of the
Column centers its content. But for this to have any effect, the column should take up the full width of its container. This is achieved using the
Modifiers are a key component of Compose Multiplatform. This is a primary mechanism you use to adjust the appearance or behavior of composables in the UI. Modifiers are created using methods of the
Modifier type. When you chain these methods, each call can change the
Modifier returned from the previous call, making the order significant. See JetPack Compose documention for more details.
Managing the state
The final aspect of the sample composable is how the state is managed. There are two properties in the
showImage. They are built using the
mutableStateOf() function, which means they are state objects that can be observed.
These state objects are wrapped in a call to the
remember() function, meaning that they are built once and then retained by the framework. For example, when you perform the declaration:
You're creating a property whose value is a state object containing a boolean. The framework caches this state object so composables can observe it.
When the value of the state changes, any composables that observe it are re-invoked. This allows any of the widgets they produce to be redrawn. This is called a recomposition.
In your application, the only place where the state is changed is in the click event of the button. This event changes the value of both properties. The
onClick event handler flips the value of the
showImage property and adds the name of the platform to the
The changes occur when:
The button is redrawn because the nested
The image is shown or hidden because the parent
Launching UI on different platforms
App() function execution is different for each platform. On Android, it's managed by an activity, on iOS by a view controller, and on desktop by a window. Let's examine each of them.
For Android, open the
MainActivity.kt file in
This is an Android activity called
MainActivity that invokes the
For iOS, open the
MainViewController.kt file in
This is a view controller that performs the same role as an activity on Android. Notice that both iOS and Android types simply invoke the
For desktop, look again at the
main() function in
application()function launches a new desktop application.
This function takes a lambda, where you initialize the UI. Typically, you create a
Windowwith properties and instructions on how to react when the window is closing. In this case, the whole application shuts down.
Inside this window, you can place your content. As with Android and iOS, the only content is the
App function doesn't declare any parameters. In a larger application, you typically use parameters to pass to platform-specific dependencies. These dependencies could be created by hand or using a dependency injection library.
In the next part of the tutorial, you'll add a dependency to the project and modify the user interface.