Slide 1

Slide 1 text

A Composable new world Photo by Greg Rosenke on Unsplash @cafonsomota

Slide 2

Slide 2 text

👨💻 Android GDE 🗣 Founder @GDGCoimbra and co-founder @Kotlin_Knights ✍ Author @rwenderlich 🎙 Podcaster wannabe 🗺 Loves travel, photography and running @cafonsomota

Slide 3

Slide 3 text

🖥 speakerdeck.com/cmota/a-composable-new-world 👉 github.com/cmota/unsplash-compose 🚀 github.com/cmota/kmp-a-multiplatform-triathlon @cafonsomota Materials

Slide 4

Slide 4 text

A brief history of (android) time

Slide 5

Slide 5 text

Android * Declarative UI Patterns (I/O’19) - https://www.youtube.com/watch?v=VsStyq4Lzxo 2008 2009 2010 1.0 A lot of Android version in between Android Studio 2013 2014 2015 2016 2017 2018 ART RecyclerView Constraint Layout Arch Components Kotlin

Slide 6

Slide 6 text

Android 2019 2021 Kotlin Jetpack Compose 1.0 2020 2018aaaaa 2017asda

Slide 7

Slide 7 text

Android 2019 2021 Kotlin Jetpack Compose 1.0 2020 2018aaaaa 2017asda

Slide 8

Slide 8 text

Jetpack Compose 1.0 Released: July 28th 2021

Slide 9

Slide 9 text

Jetpack Compose 1.0.1 (with Kotlin 1.5.21 support)

Slide 10

Slide 10 text

dev-reactions/it-works.gif

Slide 11

Slide 11 text

Before we start

Slide 12

Slide 12 text

dev-reactions/god-mode.gif

Slide 13

Slide 13 text

1. Git Clone • github.com/cmota/unsplash-compose 2. Download Android Studio Arctic Fox* • developer.android.com/studio 3. Create your Unsplash API account • unsplash.com/developers Materials * ⚠ There’s a Specific version for Mac m1

Slide 14

Slide 14 text

Materials Unsplash Compose Android app

Slide 15

Slide 15 text

Jetpack Compose

Slide 16

Slide 16 text

What’s Compose? verb 1. 
 write or create (a work of art, especially music or poetry). "he composed the First Violin Sonata four years earlier" Definitions from Oxford Languages

Slide 17

Slide 17 text

developer.android.com/jetpack/compose

Slide 18

Slide 18 text

Jetpack Compose MODERN FRAMEWORK Declarative UI Less code Smaller APK’s Kotlin Accelerate development Intuitive Open-source Unbundled from OS

Slide 19

Slide 19 text

Jetpack Compose MODERN FRAMEWORK Declarative UI Less code Kotlin Accelerate development Intuitive Open-source Smaller APK’s Unbundled from OS

Slide 20

Slide 20 text

Declarative UI

Slide 21

Slide 21 text

Declarative UI Imperative-UI VS

Slide 22

Slide 22 text

Imperative UI Exercise: Implementing a List This is item 1 This is item 2 This is item 3 This is item 4 This is item 5 This is item 6

Slide 23

Slide 23 text

Imperative UI Exercise: Implementing a List 1. Create an activity MainActivity.kt

Slide 24

Slide 24 text

Imperative UI Exercise: Implementing a List 1. Create an activity 2. Create the correspondent xml activity_main.xml

Slide 25

Slide 25 text

Imperative UI Exercise: Implementing a List 1. Create an activity 2. Create the correspondent xml 3. Create a fragment MainFragment.kt

Slide 26

Slide 26 text

Imperative UI Exercise: Implementing a List 1. Create an activity 2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml fragment_main.xml

Slide 27

Slide 27 text

Imperative UI Exercise: Implementing a List 1. Create an activity 2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml 5. Create a recycler view RecyclerView

Slide 28

Slide 28 text

Imperative UI Exercise: Implementing a List 1. Create an activity 2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml 5. Create a recycler view 6. Create the adapter Adapter

Slide 29

Slide 29 text

Imperative UI Exercise: Implementing a List 1. Create an activity 2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml 5. Create a recycler view 6. Create the adapter 7. Create the correspondent xml for the items item_adapter.xml

Slide 30

Slide 30 text

Imperative UI Exercise: Implementing a List item_adapter.xml files created 5 (It can be more if we want to add further customization) Lines of code written +200 (Between declarations and xml attributes)

Slide 31

Slide 31 text

Imperative UI Exercise: Implementing a List item_adapter.xml • Time consuming • Error prone • Several files created • Increasing APK size • Coupled components

Slide 32

Slide 32 text

Imperative UI Exercise: Changing the state of a view Hello world.

Slide 33

Slide 33 text

How to change the access and change the state of a view Imperative UI Exercise: Changing the state of a view Hello world. A brief history on or

Slide 34

Slide 34 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text TextView greetings = (TextView) findViewById(R.id.tv_greeting) greetings.text = “Hello world.”

Slide 35

Slide 35 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text @BindView(R.id.tv_greeting) TextView greetings; greetings.text = “Hello world.” github.com/JakeWharton/butterknife

Slide 36

Slide 36 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text TextView greetings = (TextView) findViewById(R.id.tv_greeting) greetings.text = “Hello world.”

Slide 37

Slide 37 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text TextView greetings = findViewById(R.id.tv_greeting) greetings.text = “Hello world.”

Slide 38

Slide 38 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text import kotlinx.android.synthetic.activity_main.* tv_greeting.text = “Hello world.”

Slide 39

Slide 39 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text import kotlinx.android.synthetic.activity_main.* tv_greeting.text = “Hello world.” DEPRECATED

Slide 40

Slide 40 text

Imperative UI Exercise: Changing the state of a view Hello world. android:Id = “@+id/tv_greeting” Text buildFeatures.viewBinding true private lateinit var binding: FragmentMainBinding override fun onCreateView( infltr: LayoutInflater, container: ViewGroup?, state: Bundle?): View { binding = FragmentMainBinding.inflate(infltr, container, false) return binding.root } binding.tvGreeting.text = “Hello world.” build.gradle

Slide 41

Slide 41 text

Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends

Slide 42

Slide 42 text

Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView

Slide 43

Slide 43 text

Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView ViewGroup

Slide 44

Slide 44 text

Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView ViewGroup extends LinearLayout

Slide 45

Slide 45 text

Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView ViewGroup extends LinearLayout RelativeLayout …

Slide 46

Slide 46 text

Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java 30407 Lines of code TextView extends ImageView ViewGroup extends LinearLayout RelativeLayout …

Slide 47

Slide 47 text

Imperative UI With 30407 lines of code and several classes that extend it - Difficult to scale - Hard to maintain - Every change might reflect on a lot of classes - Bundled to the OS and OEM’s implementation of these components

Slide 48

Slide 48 text

Goals Unbundle from platform releases Faster to implement new designs (views/components) Clarify state ownership and event handling * Adapted from declarative UI patterns (Google I/O’19) - https://www.youtube.com/watch?v=VsStyq4Lzxo&t

Slide 49

Slide 49 text

Shifting paradigms Imperative UI Ui as a function | Kotlin code XML java | kotlin code Layouts Attrs Styles … Declarative ui

Slide 50

Slide 50 text

Shifting paradigms Imperative UI What should happen How it should happen Declarative ui

Slide 51

Slide 51 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050

Slide 52

Slide 52 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI

Slide 53

Slide 53 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding badge

Slide 54

Slide 54 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding badge

Slide 55

Slide 55 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Fire

Slide 56

Slide 56 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Fire

Slide 57

Slide 57 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Paper

Slide 58

Slide 58 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Paper

Slide 59

Slide 59 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count > 0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Badge number

Slide 60

Slide 60 text

Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 @Composable fun BadgedEnvelope(count: Int) { Envelope(fire=count > 99, paper=count > 0) { if (count > 0) { Badge(text="$count") } } } Declarative UI

Slide 61

Slide 61 text

Declarative UI Winner

Slide 62

Slide 62 text

Compose

Slide 63

Slide 63 text

State of compose

Slide 64

Slide 64 text

State of compose

Slide 65

Slide 65 text

State of compose 🤔

Slide 66

Slide 66 text

• compose.animation • Animations library to enrich user experience • compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose

Slide 67

Slide 67 text

• compose.animation • Animations library to enrich user experience • compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material

Slide 68

Slide 68 text

• compose.animation • Animations library to enrich user experience • compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose Compose compiler Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material Compose Runtime

Slide 69

Slide 69 text

Compose compiler • Written in Kotlin • Transforms @Composable functions into UI • Doesn’t use the Annotation Processor • The plugin works at system/code generation level • Doesn’t impact build times • Open source • Available in AOSP Compose compiler Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material Compose Runtime android.googlesource.com/platform/frameworks/support/+/HEAD/compose/compiler

Slide 70

Slide 70 text

Compose Runtime • Platform agnostic • DOESN’T KNOW WHAT ANDROID OR UI ARE • TrEE MANAGEMENT SOLUTION Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material

Slide 71

Slide 71 text

Compose COMPILER/Runtime What this means is that Compose is, at its core, a general-purpose tool for managing a tree of nodes of any type. Well a “tree of nodes” describes just about anything, and as a result Compose can target just about anything. Jake Wharton - a Jetpack Compose by Any other name jakewharton.com/a-jetpack-compose-by-any-other-name/

Slide 72

Slide 72 text

• compose.animation • Animations library to enrich user experience • compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material

Slide 73

Slide 73 text

Compose UI toolkit • compose.ui • Handles Input Management, Drawing, Layouts, etc. • Compose.foundation • Contains Basic building: Row, Column, Text, iMage, etc. • Compose.material • Material design system to use on your view components • Compose.animation • Animations to use easily and out side of the box Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose Foundation Compose Material Compose UI

Slide 74

Slide 74 text

Compose UI Raspberry pi compose Compose compiler Compose Runtime Compose UI ANdroid Compose UI Desktop Compose UI Web Compose UI Console

Slide 75

Slide 75 text

blog.jetbrains.com/kotlin/2021/08/compose-multiplatform-goes-alpha/

Slide 76

Slide 76 text

Should I switch to compose?

Slide 77

Slide 77 text

Apps in Production* *doesn’t mean they are 100% written in Compose

Slide 78

Slide 78 text

Jetpack compose - before and after By Chris Banes github.com/chrisbanes/tivi

Slide 79

Slide 79 text

medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes APK Size 1250 2500 3750 5000 Pre-Compose (4.49 MB) Compose (2.39 MB) 4.14 MB 2.32 MB 69 KB 347 KB 4.49MB 2.32 MB -46%

Slide 80

Slide 80 text

medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes Method 12500 25000 37500 50000 Pre-Compose (40029) Compose (23689) 40029 23689 40029 methods 23689 methods -17% Count

Slide 81

Slide 81 text

medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes Lines of 5000 10000 15000 20000 Pre-Compose (19478) Compose (15407) 15827 14606 19478 Lines of code 15407 lines of code Source Code 3651 801

Slide 82

Slide 82 text

medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes Build 30 60 90 120 Pre-Compose (108,71 s) Compose (76,96 s) 108,71 76,96 108,71 seconds 76,96 seconds -29% Speed

Slide 83

Slide 83 text

YES Should I switch to compose?

Slide 84

Slide 84 text

Compose-ready libraries

Slide 85

Slide 85 text

github.com/google/accompanist Accompanist 📐 Insets 🍫 System UI Controller 🎨 AppCompat Theme Adapter 🧭✨Navigation-Animation 🧭🎨 Navigation-Material 🖌 Drawable Painter ⬇ Swipe to Refresh 📖 Pager 📫 Permissions ⏳ Placeholder 🌊 Flow Layouts

Slide 86

Slide 86 text

github.com/google/accompanist Accompanist 📐 Insets 🍫 System UI Controller 🎨 AppCompat Theme Adapter 🧭✨Navigation-Animation 🧭🎨 Navigation-Material 🖌 Drawable Painter ⬇ Swipe to Refresh 📖 Pager 📫 Permissions ⏳ Placeholder 🌊 Flow Layouts Keyboard IME animations are now available starting on minSDK 21 (through Jetpack Compose)

Slide 87

Slide 87 text

coil-kt.github.io/coil/compose/ Coil

Slide 88

Slide 88 text

lottie github.com/airbnb/lottie/blob/master/android-compose.md

Slide 89

Slide 89 text

How to Start?

Slide 90

Slide 90 text

How to Start?

Slide 91

Slide 91 text

Configuration android { defaultConfig { minSdk 21 … } kotlinOptions { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion '1.5.10' } } build.gradle

Slide 92

Slide 92 text

Configuration android { defaultConfig { minSdk 21 … } kotlinOptions { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion '1.5.10' } } build.gradle

Slide 93

Slide 93 text

Configuration android { defaultConfig { minSdk 21 … } kotlinOptions { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion '1.0.0' kotlinCompilerVersion '1.5.10' } } build.gradle

Slide 94

Slide 94 text

Configuration android { defaultConfig { minSdk 21 … } kotlinOptions { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion '1.0.0' kotlinCompilerVersion '1.5.10' } } build.gradle

Slide 95

Slide 95 text

Configuration dependencies { implementation "androidx.compose.ui:ui:1.0.0" implementation "androidx.compose.material:material:1.0.0" implementation "androidx.compose.ui:ui-tooling-preview:1.0.0" implementation "androidx.activity:activity-compose:1.3.1" } build.gradle

Slide 96

Slide 96 text

Adding text XML Hello world! Kt

Slide 97

Slide 97 text

Adding text XML Hello world! Without Compose

Slide 98

Slide 98 text

Adding text XML Hello Android! Without Compose val greetings = findViewById(R.id.tv_greetings) greetings.text = "Hello Android!” Kt

Slide 99

Slide 99 text

Adding text Hello world! With Compose Text(text = "Hello world!”) Kt

Slide 100

Slide 100 text

Adding text Hello world! With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } Kt

Slide 101

Slide 101 text

Adding text With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } Kt

Slide 102

Slide 102 text

Adding text With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } Kt

Slide 103

Slide 103 text

Adding text With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } Kt

Slide 104

Slide 104 text

Adding text With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } Kt

Slide 105

Slide 105 text

View Groups Hello world! XML Number of co ff ees: 0

Slide 106

Slide 106 text

View Groups Hello world! Without compose LinearLayout> XML Number of co ff ees: 0

Slide 107

Slide 107 text

View Groups Hello world! With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } Kt

Slide 108

Slide 108 text

View Groups Hello world! With compose @Composable fun Greeting(name: String) { Text(text = "Hello $name!”) Text(text = "Number of coffees: 0") } Kt Number of co ff ees: 0

Slide 109

Slide 109 text

View Groups Hello world! With compose @Composable fun Greeting(name: String) { Column { Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0

Slide 110

Slide 110 text

View Groups Hello world! With compose @Composable fun Greeting(name: String) { Column { Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0

Slide 111

Slide 111 text

View Groups Hello world! With compose @Composable fun Greeting(name: String) { Row { Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0

Slide 112

Slide 112 text

Number of co ff ees: 0 View Groups With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.background(Color.Green) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Hello world!

Slide 113

Slide 113 text

View Groups With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.background(Color.Green) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Hello world! Number of co ff ees: 0

Slide 114

Slide 114 text

Hello world! Number of co ff ees: 0 View Groups With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt

Slide 115

Slide 115 text

Hello world! Number of co ff ees: 0 View Groups With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) .padding(16.dp) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt

Slide 116

Slide 116 text

Hello world! Number of co ff ees: 0 View Groups With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt

Slide 117

Slide 117 text

Hello world! View Groups With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ){ Text( text = "Hello $name!”, color = Color.White ) Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0

Slide 118

Slide 118 text

Hello world! Images XML Number of co ff ees: 0

Slide 119

Slide 119 text

Hello world! Images Without compose LinearLayout> XML Number of co ff ees: 0

Slide 120

Slide 120 text

Hello world! Images With compose @Composable fun Greeting(name: String) { Column(…) { Text( text = "Hello $name!", color = Color.White ) Text(text = "Number of coffees: 0") Image( painter = painterResource(id = R.drawable.ic_launcher), contentDescription = stringResource(id = R.string.app_name) ) } } Kt Number of co ff ees: 0

Slide 121

Slide 121 text

Hello world! Images With compose @Composable fun Greeting(name: String) { Column(…) { Text( text = "Hello $name!", color = Color.White ) Text(text = "Number of coffees: 0") Image( painter = painterResource(id = R.drawable.ic_launcher), contentDescription = stringResource(id = R.string.app_name) ) } } Kt Number of co ff ees: 0

Slide 122

Slide 122 text

Hello world! Button XML Number of co ff ees: 0 +

Slide 123

Slide 123 text

Hello world! Button Without compose LinearLayout> XML Number of co ff ees: 0 +

Slide 124

Slide 124 text

Hello world! Button With compose @Composable fun Greeting(name: String) { Column(…) { … Text(text = "Number of coffees: 0") … Button(onClick = { /* TODO */ }) { Text("+") } } } Kt Number of co ff ees: 0 +

Slide 125

Slide 125 text

Hello world! Button With compose @Composable fun Greeting(name: String) { Column(…) { … Text(text = "Number of coffees: 0") … Button(onClick = { /* TODO */ }) { Text("+") } } } Kt Number of co ff ees: 0 +

Slide 126

Slide 126 text

Hello world! State Kt Number of co ff ees: 0 +

Slide 127

Slide 127 text

Hello world! State Without compose var count = 0 binding.tvMessage = getString(R.string.number_coffee, count) binding.btn_increment.setOnClickListener { count ++ } Kt Number of co ff ees: 0 +

Slide 128

Slide 128 text

Hello world! State With compose @Composable fun Greeting(name: String) { Column(…) { … val count = remember { mutableStateOf(0) } Text(text = "Number of coffees taken: ${count.value}") … Button(onClick = { count.value = count.value + 1 }) { Text("+") } } } Kt Number of co ff ees: 0 +

Slide 129

Slide 129 text

Hello world! State With compose @Composable fun Greeting(name: String) { Column(…) { … val count = remember { mutableStateOf(0) } Text(text = "Number of coffees taken: ${count.value}") … Button(onClick = { count.value = count.value + 1 }) { Text("+") } } } Kt Number of co ff ees: 0 +

Slide 130

Slide 130 text

Hello world! State With compose @Composable fun Greeting(name: String) { Column(…) { … val count = remember { mutableStateOf(0) } Text(text = "Number of coffees taken: ${count.value}") … Button(onClick = { count.value = count.value + 1 }) { Text("+") } } } Kt Number of co ff ees: 0 +

Slide 131

Slide 131 text

Live Demo

Slide 132

Slide 132 text

dev-reactions/live-coding.gif

Slide 133

Slide 133 text

Resources

Slide 134

Slide 134 text

• Jetpack Compose samples (Google) • github.com/android/compose-samples • A curated list of Jetpack Compose libraries, projects, articles and resources • github.com/jetpack-compose/jetpack-compose-awesomeAnimations library to enrich user experience • Jetpack Compose Catalog • jetpackcompose.app • Jetpack/JetBrains Compose Playground • foso.github.io/Jetpack-Compose-Playground/ • Community • twitch.tv/intelligibabble • joebirch.co/tag/jetpack-compose/ • jorgecastillo.dev/ Resources

Slide 135

Slide 135 text

A Composable new world Photo by Greg Rosenke on Unsplash @cafonsomota