A new Android native UI development framework, Jetpack Compose, was unveiled at Google/IO this year. Like Apple’s SwiftIUI, Jetpack Compose is a declarative UI framework. With android and Apple launching their own UI development frameworks Jetpack Compose and SwiftIUI this year, mobile operating systems have officially embraced declarative UI development mode.

The past and present of declarative UI

In fact, declarative UI is not a new technology, as early as 2006, Microsoft has released its new generation of interface development framework WPF, which uses XAML markup language, supports bidirectional data binding, reusable templates and other features.

In 2010, the Qt team, led by Nokia, released its next-generation interface solution, Qt Quick, which was also Declarative. Qt Quick was originally named Qt Declarative. QML also supports data binding, modularity, and built-in JavaScript, allowing developers to create simple, interactive prototypes using only QML.

Declarative UI frameworks have exploded in recent years, culminating in Web development. React laid a solid foundation for declarative UI and will continue to lead its future development. The subsequent release of Flutter brings the idea of declarative UI to mobile development…

Declarative UI means that you describe what kind of UI you want, and when the state changes, the interface “renders” as described earlier to get the state exactly right, rather than telling the program what to do step by step and maintaining various states. Digression, this is not the focus of today’s article, a little understanding of good, other will not be extended in this article. More introduction about declarative, suggestion: look at this article zhuanlan.zhihu.com/p/68275232

Let’s return to the focus of this article, Jetpack Compose.

Jetpack Compose

Jetpack Compose is a modern toolkit for building native Android UIs based on a declarative programming model, so you can simply describe what the UI looks like, while Compose does the rest — your UI updates automatically when the state changes. Because Compose is built on Kotlin, it is fully interoperable with the Java programming language and has direct access to all Android and Jetpack apis. It’s also fully compatible with existing UI toolkits, so you can mix old views with new ones, and design with Material and animation from the start.

Jetpack Compose environment preparation and Hello World

Whenever we learn a new language, we start with a Hello world, and today we’re going to start Jetpack Compose with a Hello world. To get the best experience of Jetpack Compose, you’ll need to download the latest version of Android Studio preview (Android Studio 4.0). Because Android Studio 4.0 has added support for Jetpack Compose, such as the new Compose template and Compose in-time preview.

There are two ways to start your development efforts with Jetpack Compose:

  • Add Jetpack Compose to your existing project
  • Create a new application that supports Jetpack Compose

Let’s take a look at each of these methods.

1. Add Jetpack Compose to your existing project

If you want to use Jetpack Compose in an existing project, you need to configure the necessary Settings and dependencies:

Gradle configuration

Gradle: Set the minimum API version supported by your app to 21 or higher and enable Jetpack Compose enable in your app directory.

android {
    defaultConfig {
        ...
        minSdkVersion 21
    }

    buildFeatures {
        // Enables Jetpack Compose for this module
        compose true}...// Set both the Java and Kotlin compilers to target Java 8.compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions  { jvmTarget ="1.8"}}Copy the code

(2) Use the experimental versionKotlin-GradleThe plug-in

For Jetpack Compose, you need a test version of the kotlin-gradle plugin. Add the following code to build. Gradle:

buildscript {
    repositories {
        google()
        jcenter()
        // To download the required version of the Kotlin-Gradle plugin,
        // add the following repository.
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap'}... dependencies { classpath'com. Android. Tools. Build: gradle: 4.0.0 - alpha01'
        classpath 'org. Jetbrains. Kotlin: kotlin - gradle - plugin: 1.3.60 eap - 25'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap'}}}Copy the code

(3) Add Jetpack Compose toolkit dependency

Add the Jetpack Compose toolkit dependency to build.gradle in your app directory as follows:

dependencies {
    // You also need to include the following Compose toolkit dependencies.
    implementation 'androidx. UI: UI - tooling: 0.1.0 from - dev02'
    implementation 'androidx. UI: UI - layout: 0.1.0 from - dev02'
    implementation 'androidx. UI: UI - material: 0.1.0 from - dev02'. }Copy the code

Ok, that’s the end of your preparation and you’re ready to start writing code, but there’s another way to plug into Jetpack Compose, so let’s take a look.

2. Create a new app that supports Jetpack Compose

Creating a new project that supports Jetpack Compose is a lot easier than adding It to your existing app, because Android Studio 4.0 provides a new Compose template that you can use to create your app. All of the above configuration items automatically do it for us.

To create an application that supports Jetpack Compose, follow these steps:

    1. If you’re in Android Studio’s welcome window, clickStart a new Android Studio projectIf you already have the Android Studio project open, select it from the top menu barFile > New > New Project
    1. inSelect a Project TemplateWindow, selectEmpty Compose ActivityAnd hit Next
    1. inConfigure your projectWindow, do the following steps:
    • Set a.The project name.The package nameandSave the location
    • B. Note that Kotlin is the only option in the language down menu because Jetpack Compose can only run if it is written in Kotlin.
    • c. Minimum API levelFrom the drop-down menu, select 21 or higher
    1. Click on theFinish

Now you can write your app using Jetpack Compose.

3. Hello wold

Add the following code to mainactivity.kt:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContent {
             Text("Hello, Android Tech grocery store")}}}Copy the code

Jetpack Compose is built around the Composable function. These functions allow you to programmatically define your application’s UI by describing the shape and data dependencies of your application, rather than focusing on the UI building process. To create a Composable function, just add a @composable annotation in front of the function name. The above Text is a Composable function.

Define onecomposablefunction

A composable function can only be called in the scope of another composable function. To make a function into a composable function, add @composable to the function name and move the setContent part of the above code outside. Extract into a composable function and pass a parameter name to the text element.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContent {
            Greeting("Android Technology Grocery Store")}}}@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")}Copy the code

Four, layout,

UI elements are hierarchical, with elements contained within other elements. In Jetpack Compose, you can build your UI hierarchy by calling composable functions from other Composable functions.

In the Android XML layout, if you want to display a vertical layout, the longest one is the LinearLayout. Set the Android :orientation value to vertical, and the child elements will be arranged vertically. How to achieve vertical layout? Let’s just add a couple of Text.

1. Add multiple texts

In the example above, we added a Text display Text, now we add three Text, code like this:

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

@Composable
fun NewsStory(a) {
    Text("I'm super ❤️JetPack Compose!")
    Text("Android Technology Grocery Store")
    Text("Still Fantsea.")}Copy the code

As you can see from the figure above, we have added three text elements, but since we haven’t provided any information on how to arrange them, the three text elements are drawn on top of each other, making the text unreadable.

2. Use the Column

To make the superimposed Text vertically aligned, we need to use the Column function. Does this look familiar to those who have written about flutter? Yes, the name and function of the Column Widget inside the Flutter are exactly the same, even their properties are identical.

@Composable
fun NewsStory(a) {
    Column { // Add Column to make the layout vertical
        Text("I'm super ❤️JetPack Compose!")
        Text("Android Technology Grocery Store")
        Text("Still Fantsea.")}}Copy the code

The effect is as follows:

As you can see, the previous overlapping layout is now vertically aligned, but by default, one after the other, without any spacing, starting at the top left corner. Next, let’s set some styles for Column.

3. ToColumnAdd the style

When Column () is called, you can pass parameters to Column () to set the size, position, and arrangement of the Column’s children.

@Composable
fun NewsStory(a) {
    Column (
        crossAxisSize = LayoutSize.Expand,
        modifier = Spacing(16.dp)
    ){ // Add Column to make the layout vertical
        Text("I'm super ❤️JetPack Compose!")
        Text("Android Technology Grocery Store")
        Text("Still Fantsea.")}}Copy the code

As shown in the image above, we fill in the padding. The other effects are almost the same. The Settings in the code above are explained as follows:

  • CrossAxisSize: Specify Column component (note: Compose all components are composable functions and cross SAXisSize to LayoutSize.Expand indicates that the Column width should be the maximum width allowed by its parent component. It’s match_parant in a traditional layout, and it has a value of LayoutSize.Wrap, which you can tell by its name, is wrap_content in a traditional layout.

  • Modifier: Enables you to make other format changes. In this case, we will apply a Spacing modifier that distances Cloumn from the surrounding views.

4. How to display a picture?

In the original Android layout, there is an ImageView control for displaying images. You can set the local image address or Bitmap to display the images.

We will download the image locally, add it to explorer and call it header.png. We will change the NewsStory () method above to get the image from resources folder and draw the image by DrawImage() :

@Composable
fun NewsStory(a) {
    // Get the image
    val image = +imageResource(R.mipmap.header)
    Column (
        crossAxisSize = LayoutSize.Expand,
        modifier = Spacing(16.dp)
    ){ // Add Column to make the layout vertical
        // Display the image
        DrawImage(image)
        
        Text("I'm super ❤️JetPack Compose!")
        Text("Android Technology Grocery Store")
        Text("Still Fantsea.")}}Copy the code

As you can see, the image doesn’t display in the correct column. Let’s fix it.

Images have been added to the layout, but are expanded to fill the entire view, and are stacked with text, with text displayed on top. To set a graphic style, place it in Container(another control similar to flutter)

  • Container: a generic content object for holding and arranging other UI elements. You can then apply the size and location Settings to the container.
@Composable
fun NewsStory(a) {
    // Get the image
    val image = +imageResource(R.mipmap.header)
    Column (
        crossAxisSize = LayoutSize.Expand,
        modifier = Spacing(16.dp)
    ){ // Add Column to make the layout vertical
        // Put it in the container and set the size
        Container(expanded = true, height = 180.dp) {
            // Display the image
            DrawImage(image)
        }
        Text("I'm super ❤️JetPack Compose!")
        Text("Android Technology Grocery Store")
        Text("Still Fantsea.")}}Copy the code

  • expanded : Specify the size of the Container, which defaults to false (the size of the Container is the size of the child component, equivalent to wrap_content). If set to true, specify that the size of the Container is the maximum size allowed by the parent control, equivalent to match_parent.

  • Height: Sets the height of the Container. The height property takes precedence over expanded, so expanded is overridden. In the example above, set height to 180dp, that is, the width of the Container is the width of the parent control and the height is 180DP

5. Add spacingSpacer

We can see that there is no spacing between the image and the text. In traditional layout, we can add the Margin property and set the spacing. In Jetpack Compose, we can use HeightSpacer() and WidthSpacer() to set the vertical and horizontal spacing

 HeightSpacer(height = 20.dp) // Set the vertical spacing to 20dp
 WidthSpacer(width = 20.dp) // Set the horizontal spacing to 20dp
Copy the code

In the example above, let’s add 20dp space between the image and the text:

@Composable
fun NewsStory(a) {
    // Get the image
    val image = +imageResource(R.mipmap.header)
    Column (
        crossAxisSize = LayoutSize.Expand,
        modifier = Spacing(16.dp)
    ){ // Add Column to make the layout vertical
        // Put it in the container and set the size
        Container(expanded = true, height = 180.dp) {
            // Display the image
            DrawImage(image)
        }

        HeightSpacer(height = 20.dp) // Add 20dp vertical spacing

        Text("I'm super ❤️JetPack Compose!")
        Text("Android Technology Grocery Store")
        Text("Still Fantsea.")}}Copy the code

V. Use Material Design

Compose is designed to support Material Design principles. Many components implement Material Design and are available right out of the box. In this section, you’ll use some Material widgets to style your app

Add 1.Shapestyle

Shape is one of the pillars of Material Design system. We use clip function to round the image.

@Composable
fun NewsStory(a) {
    // Get the image
    val image = +imageResource(R.mipmap.header)
    Column (
        crossAxisSize = LayoutSize.Expand,
        modifier = Spacing(16.dp)
    ){ // Add Column to make the layout vertical
        // Put it in the container and set the size
        Container(expanded = true, height = 180.dp) {
            Clip(shape = RoundedCornerShape(10.dp)) {
                // Display the image
                DrawImage(image)
            }
           
        }

        HeightSpacer(height = 20.dp) // Add 20dp vertical spacing

        Text("I'm super ❤️JetPack Compose!")
        Text("Android Technology Grocery Store")
        Text("Still Fantsea.")}}Copy the code

The shape is not visible, but our image has been cropped to the set shape style, so the image has rounded corners as shown in the image above.

2. ToTextAdd some styles

With Compose, you can easily leverage Material Design principles. Apply the MaterialTheme () to the created component

@Composable
fun NewsStory(a) {
    // Get the image
    val image = +imageResource(R.mipmap.header)
    // Use Material Design
    MaterialTheme() {
        Column (
            crossAxisSize = LayoutSize.Expand,
            modifier = Spacing(16.dp)
        ){ // Add Column to make the layout vertical
            // Put it in the container and set the size
            Container(expanded = true, height = 180.dp) {
                Clip(shape = RoundedCornerShape(10.dp)) {
                    // Display the image
                    DrawImage(image)
                }

            }

            HeightSpacer(height = 20.dp) // Add 20dp vertical spacing

            Text("I'm super ❤️JetPack Compose!")
            Text("Android Technology Grocery Store")
            Text("Still Fantsea.")}}}Copy the code

In the code above, after adding the MaterialTheme, re-run the MaterialTheme with no change, and the text now uses the default text style of the MaterialTheme. Next, we apply a specific paragraph style to each text element.

@Composable
fun NewsStory(a) {
    // Get the image
    val image = +imageResource(R.mipmap.header)
    // Use Material Design
    MaterialTheme() {
        Column (
            crossAxisSize = LayoutSize.Expand,
            modifier = Spacing(16.dp)
        ){ // Add Column to make the layout vertical
            // Put it in the container and set the size
            Container(expanded = true, height = 180.dp) {
                Clip(shape = RoundedCornerShape(10.dp)) {
                    // Display the image
                    DrawImage(image)
                }

            }

            HeightSpacer(height = 20.dp) // Add 20dp vertical spacing

            Text("I'm super ❤️JetPack Compose!", style = +themeTextStyle { h5 }) // Notice the addition of style
            Text("Android Technology Grocery Store", style = +themeTextStyle { body1 }) // Notice the addition of style
            Text("Still Fantsea.", style = +themeTextStyle { body2 }) // Notice the addition of style}}}Copy the code

Now let’s see, our text styles have changed. There are 6 styles h1-H6 in the header, but the styles in HTML are very similar. The content text has styles from Body1 and Body22.

The Material palette uses some basic colors and adjusts the opacity of the text if you want to emphasize it:

  Text("I'm super ❤️JetPack Compose!", style = (+themeTextStyle { h5 }).withOpacity(0.87f))
  Text("Android Technology Grocery Store", style = (+themeTextStyle { body1 }).withOpacity(0.87f))
  Text("Still Fantsea.", style = (+themeTextStyle { body2 }).withOpacity(0.6f))
Copy the code

Sometimes the title is too long, but we don’t want to break the long title to affect our APP UI. Therefore, we can set the maximum number of lines of text to be displayed, and truncate the text beyond that.

As shown in this example, we set the maximum number of lines to be displayed to 2, and truncate the portion that is more than that:

  Text("I'm super ❤️JetPack Compose! It is easy to write, reusable and can extract many components to reuse, without managing complex state changes!",
                maxLines = 2, overflow = TextOverflow.Ellipsis,
                style = (+themeTextStyle { h5 }).withOpacity(0.87f))
Copy the code

maxLines
overflow

Compose layout preview

Starting with Android Studio 4.0, it provides the ability to preview composable functions in the IDE instead of downloading an emulator and running the app in the emulator to see the effect.

There is a limitation, however, that the Composable function cannot have parameters

The following two conditions are met:

  • The function has no arguments
  • Add before the function@Previewannotations

Preview renderings are as follows:

When the layout changes, a navigation bar appears at the top showing that the preview is out of date, and you can refresh the preview by hitting build&Refresh

This is a really nice feature. Other declarative layouts, such as React and Flutter, do not have this feature. After the layout, you have to run the flutter again to see the effect.

One of the cool things about Compose is that you can preview multiple streams at oncecomposableFunction.

The effect is as follows:

Seven,

Jetpack Compse is still an experimental version, so there are definitely a lot of issues that can’t be used in commercial projects right now, but that shouldn’t stop us from learning and experimenting with it. Declarative UI frameworks have grown rapidly in recent years, and React has laid a solid foundation for declarative UI. The launch of Flutter brings the idea of declarative UI to mobile development. Apple and Google have released their own declarative UI frameworks SwiftUI and Jetpack Compose, respectively. In the future, native UI layouts, declarative UI, may become the mainstream.

That’s all for this article, I hope you found it useful!

If you like my article, please follow my public account Android technology grocery store, Jian Shu or Github! Wechat official account: Android technology Grocery Store

Jane: www.jianshu.com/u/35167a70a…

GitHub:github.com/pinguo-zhou…