Writing Your First Jetpack Compose App

This tutorial assumes the following.

  • You are an Android Developer (minimum: Entry-level)
  • You use Android studio
  • You are comfortable using Kotlin
  • You followed the first two tutorials

If you followed the last post, you should have a new project started up. In Jetpack Compose we do not build our User Interfaces with XML instead we follow a Declarative Programming pattern, where we declare what the UI elements should be and the system handles the task of producing the declared elements.

For example, when we declare a Column in Jetpack Compose, we are unbothered at the higher lever about what kind of layout Jetpack draws, is its a simple Coordinator Layout or a Constraint Layout. all we care about is that the terms we defined for our layout are fulfilled and we can interact with the UI.

In JC most of the time the root element is usually a Column, unless we want to apply a theme to the layout, then we can wrap the Column in a MaterialTheme element. we also use the @Composable annotation to tell JC what functions represent our views that should be drawn on the screen, finally to view our layout in realtime we need to call the @Composable annotated function from another function that contains the @Preview annotation alongside @Composable in this order. All these would make more sense shortly.

Head over to the MainActivity file and create a function called salutation in the MainActivity file, but outside the MainActivity class.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello world!")
        }
    }
}

@Composable
fun salutation(name: String) {
    Text (text = "Hello $name!")
}

if you noticed, we have no setContentView() method, instead, we have a setContent{ } that takes a composable function.

The salutation function is declared with the @Composable annotation and is passed a name, and uses that name to configure the text element. the @Composable annotation tells JC to build the contents of the function as a UI.

Preview your UI in Android Studio

Android Studio lets you preview your composable functions directly as you would an XML layout, instead of needing to download the app to your Android device or emulator. The main caveat is that the composable function must not take any parameters. thus we can’t preview the salutation() function directly. Instead, make we need to make a second function named previewSalutation() below the salutation() function, which calls salutation() with an appropriate parameter. Add the @Preview annotation before @Composable.

@Preview
@Composable
fun previewSalutation() {
    salutation("Android")
}

You can see the @Preview annotation comes before the @Composable annotation and does not take any parameters.

To view the Preview, Rebuild your project. The app itself doesn’t change since the new previewSalutation() function isn’t called anywhere, but Android Studio adds a preview window. This window shows a preview of the UI elements created by composable function marked with the @Preview annotation. To update the previews at any time, click the refresh button at the top of the preview window.

Next, delete the Text(“Hello world!”) line and replace with salutation(“Android”), refresh and view the UI o the right side of the IDE.

NB: you can toggle the views between Code only, Design Only and split by using the buttons on the right of the toolbar. we use split mode for this example.

You can equally run the app to see the text changes.

Working with Texts in Jetpack Compose

Let us replace the salutation function name with NewsStory() and update the onCreate(), also rename previewSalutation() to DefaultPreview() and call NewsStory() from within. the new class should look like this

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NewsStory()
        }
    }
}

@Composable
fun NewsStory() {
    Text("Breaking: Local man is tired")
    Text("This is some description...")
    Text("January 2020")
}

@Preview
@Composable
fun DefaultPreview() {
    NewsStory()
}

It’s a best practice to create separate preview functions that aren’t called by the app; having dedicated preview functions improves performance, and also makes it easier to set up multiple previews later on. Hence we, create a default preview function that does nothing but call the NewsStory() function. As you make changes to the NewsStory() through this tutorial, the preview would reflect the changes.

This code creates three text elements inside the content view. However, since we haven’t provided any information about how to arrange them, the three text elements are drawn on top of each other, making the text unreadable.

Using Columns

The Column function, just like LinearLayout with the orientation set to vertical, lets you stack elements vertically. we wrap the 3 Texts with a Column and they align vertically.

@Composable
fun NewsStory() {
    Column {
       Text("Breaking: Local man is tired")
       Text("This is some description...")
       Text("January 2020")
    }
}

Styling the Column…

we can specify parameters that help modify how the column behaves and looks.

@Composable
fun NewsStory() {
    Column(modifier = Spacing(16.dp)) {
       Text("Breaking: Local man is tired")
       Text("This is some description...")
       Text("January 2020")
    }
}

the modifier parameter: Lets you configure the layout. here we simply apply a Spacing modifier, which insets the column from the surrounding view.

The Spacing style/setting/parameter behaves like android:margin in XML

Working With Images

@Composable
fun NewsStory() {
    val image = +imageResource(R.drawable.header)

    Column(modifier = Spacing(16.dp)) {
        DrawImage(image)

       Text("Breaking: Local man is tired")
       Text("This is some description...")
       Text("January 2020")
    }
}

using +imageResource grabs the image via the Apps Context, then we set this image by calling

DrawImage(image)

within the Column braces.

The DrawImage(image) handles displaying the image on the screen, but as we can see, the image matches the entire screen and acts as a backdrop for the Texts, this isn’t the behaviour we want so we have to specify the behaviour we need.

@Composable
fun NewsStory() {
    val image = +imageResource(R.drawable.header)

    Column(modifier = Spacing(16.dp)) {
        Container(modifier = Height(180.dp) wraps Expanded) {
                DrawImage(image)
        }

       Text("Breaking: Local man is tired")
       Text("This is some description...")
       Text("January 2020")
    }
}
  • Height: Specifies the height of the container. The height setting takes precedence over the setting for expanded; the result is that the container is sized to a height of 180 DP, but the width is the maximum allowed by its parent.
  • Expanded: Specifies the size of the container. The default is false (make the container the size of its children). By setting expanded to true, you specify that the container should be as large as its parent will allow.

Use the wraps infix function to include multiple modifiers. The outer modifier takes precedence over the inner modifier. Put Height first, so it takes precedence. The result is that the container is sized to a height of 180 DP, but the width is the maximum allowed by its parent.

From the next post, we would look at how to generally improve the UI of our app and also add a MaterialTheme

1271total visits,8visits today

Share

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *