Image by Gordon Johnson from Pixabay
With Android's fresh way of developing UI, there's little to no XML which was formerly the primary way of designing UI for Android apps. With Jetpack Compose, you just declare what you need for creating your UI by calling functions and Jetpack Compose handles the implementation. When you need your UI to reflect come changes with the user's data, the functions you created just get called again with the new data.
Jetpack Compose comes with Android Jetpack, a collection of software components launched in 2018 that work to make developing Android apps easier and more efficient. Before JC, using views was the primary way of creating UI in Android, thus, many of the apps already existing are built with views, that is why Compose can exist in harmony with views so you can be sure that you don't need to throw away all your old code with views when starting out with Compose. Instead, you can make the shift to Compose in a way that suits you best.
If you've ever programmed with Flutter, chances are, you're going to fit right in with Jetpack Compose since Compose comes with a reactive style of programming.
Setting up the dance floor
To get started with Compose you must have Android Studio Arctic Fox.
After downloading Android Studio and successfully launching it, we can create a new compose project by clicking New Project,
And then click Empty Compose Activity to start creating your Compose app,
A pop-up titled "Empty Compose Activity" appears, and we can go ahead to change our project's name to something more fitting:
The save location is where your project will locally be stored on your machine, and the package name uniquely identifies your app. The value supplied for the save location will be slightly different depending on your choices when installing Android Studio, and although you can change it and the package name, it would be better to leave it as is since the explanation given from this point is done in accordance with these exact values.
The process is smooth and free of hitches if your internet connection is enabled and stable.
If you were unable to follow along with the above steps, you can visit Android developer's official site to see more info about the setup process.
Getting to know your partner, JC
After Android Studio finishes setting up your project, you should have a file with the name MainActivity.kt
automatically shown in the editor window (the space available in Android Studio where the details of files are seen and interacted with).
You should also be able to see this sample bit of code:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FirstComposeAppTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}
}
This file belongs to the launching activity of your app called MainActivity
. The class name also points to this. An activity, is the primary component of any android app that involves continuous interaction with the user. It serves as the entry point of your app in which you can let the user interact with your app. It, most commonly, shows UI as a single screen in the app. A more in-depth explanation can be found in the Android docs. MainActivity
is your launching activity because it was automatically set as so in the AndroidManifest.xml
upon the creation of your project. AndroidManifest.xml
is a manifest file. It describes your app to Android systems, therefore, every app project you create must have it. To see what the manifest file looks like, go into the project window and double-click the manifests directory:
This opens up the manifest file in the editor window:
The highlighted part focuses on MainActivity
. For an activity to be visible to the Android system, it must be declared in the manifest file using the <activity>
tag. And this piece of XML
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
makes it the activity that the will be launched from the launcher screen.
Back to this piece of code:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FirstComposeAppTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}
}
If you've worked with views, the code should be slightly familiar. In here, our first visible step into compose starts from setContent
which has a content
parameter that takes in a composable function that returns Unit
as its argument. This content value becomes the root view of the given activity.
Take a look at setContent
's definition:
public fun ComponentActivity.setContent(
...
content: @Composable () -> Unit
) {
...
}
Before moving ahead, let's slide into what a composable function is.
A Jetpack Compose app will primarily be made up of composable functions which serve as the building blocks of your app’s UI. You’ll create your UI With composable functions or composables for short. A composable function looks like any other normal function you can find in your code, except now it's marked with an
annotation @Composable. This annotation serves as a tag on your function that tells Compose that it is specially made for producing UI. Let's look at a very basic composable function:
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
We can see the annotation @Composable, and as previously pointed out, this makes Greeting a composable function. Let's notice how we started our function name with a capital letter following a PascalCase format. Anytime your composable function returns Unit, you are advised to use PascalCase in writing its name, and also to use a noun as the name. Focusing on the function we are calling next, Text(...), is a composable function that comes by default with Jetpack Compose. It prints the String value that was passed as an argument to its parameter "text" on-screen.
We've passed in a string template that references the parameter name, thus, whatever value will be called with Greeting will be what gets shown on-screen.
The Text function’s declaration looks like this:
@Composable
fun Text(
text: String,
...
) {
...
}
If you’ve ever used views to create apps, this is similar to TextView.
Now that we know what composable functions are, let's waltz back into analyzing the piece of code in our MainActivity.onCreate
method.
From here, our next step comes with FirstComposeAppTheme
which provides our app's theme. We can use a theme to style our app by providing a pool of colors, typography, and shapes that we can use to not only fuse our brand into the app but also grant it a uniform look and feel that looks aesthetically pleasing and is also coherent. Jetpack Compose provides MaterialTheme
as the default theming system, but for more control over our app's look an feel, we can choose to build something of our own from scratch.
In our case FirstComposeAppTheme
, automatically created upon the creation of own new project, sits atop MaterialTheme
.
See the definition of FirstComposeAppTheme
:
@Composable
fun FirstComposeAppTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
Let's focus on the part about MaterialTheme
, where clearly, our FirstComposeAppTheme
just wraps around MaterialTheme
.
Now back to our code in our activity's onCreate function, we can see that setContent
is a higher-order function, so is FirstComposeAppTheme
and Surface
since they take in functions as parameters. Notice the FirstComposeAppTheme
was passed as an argument to the content parameter, using the trailing lambda syntax. Composable, Greeting
, is called in the lambda passed into Surface
with the parameter "Android". Since we have “Hello $name” already set, this should later show "Hello Android" on-screen once it is run.
The comment above the invocation of Surface,
// A surface container using the 'background' color from the theme
Surface(color = ...
tells us that we are creating a surface container and passing in the background color set in our theme.
This surface container is a Material surface, meaning that it follows Material Design language where it serves as a depiction of physical surfaces having attributes like color, elevation, opacity and shape. See it’s definition:
@Composable
fun Surface(
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
color: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(color),
border: BorderStroke? = null,
elevation: Dp = 0.dp,
content: @Composable () -> Unit
) {
…
}
You might have noticed by now how a composable is passed into another composable as its content
's argument.
Treading down our MainActivity
file allows us to see the declaration of Greeting. Below it we can see another composable function DefaultPreview
which takes no parameter but instead has an extra annotation Preview
. The Android Studio you installed comes with a preview window that allows you to view the UI built by a composable. This Preview
annotation marks a function that contains no parameter to allow its UI be shown in the Android Studio preview.
@Preview(showBackground = true)
@Composable fun DefaultPreview() {
FirstComposeAppTheme {
Greeting("Android")
}
}
In the DefaultPreview
function, FirstComposeAppTheme
function is called and the same thing done in the onCreate
function of the MainActivity is repeated. We can pass in several arguments to Preview
that control how the UI created by the composable functions we call will look like in the preview window. For example, we can supply showSystemUi = true
.
@Preview(showBackground = true, showSystemUi = true )
At the moment, we are only tweaking the values of showBackground
and showSystemUi
, to see more info about the annotation, place you mouse icon over the annotation text and wait for a pop-up to appear showing the documentation details of Preview
. If nothing appears, place your input cursor in the midst of its characters, go up to toolbar area, click View > Quick Documentation. You should probably take note of the shortcut for this action.
The preview window should be open by default,
but if it isn't, you can split the window.
Using the preview window, you can always create composables and then see how they look before deploying to your device.
Now that we've taken our first steps with compose, let's actually start dancing in my next post.
Main Sources:
Android source code
Top comments (1)
great explanation