Slide 1

Slide 1 text

luca_nicolett JETPACK COMPOSE EXPLORING A PRE-ALPHA

Slide 2

Slide 2 text

luca_nicolett JETPACK COMPOSE ๏ Luca Nicoletti ๏ Italian ๏ Android Engineer ๏ Based in London ๏ Babylon Health

Slide 3

Slide 3 text

luca_nicolett JETPACK COMPOSE EXPLORING A PRE-ALPHA

Slide 4

Slide 4 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 Android Dev 
 Summit 
 Oct 2019

Slide 5

Slide 5 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019

Slide 6

Slide 6 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 Android Dev 
 Summit 
 Oct 2019

Slide 7

Slide 7 text

luca_nicolett JETPACK COMPOSE Android Dev 
 Summit 
 Oct 2019

Slide 8

Slide 8 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 Android Dev 
 Summit 
 Oct 2019 5 months time

Slide 9

Slide 9 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 Android Dev 
 Summit 
 Oct 2019 5 months time !

Slide 10

Slide 10 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 2-3 weeks 
 after Generic blogposts
 about all the things
 announced

Slide 11

Slide 11 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 2-3 weeks 
 after Generic blogposts
 about all the things
 announced Generic blogpost
 about what is 
 Jetpack Compose

Slide 12

Slide 12 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 2-3 weeks 
 after Generic blogposts
 about all the things
 announced Generic blogpost
 about what is 
 Jetpack Compose Specific blogpost
 about Jetpack
 Compose

Slide 13

Slide 13 text

luca_nicolett JETPACK COMPOSE Google I/O
 May 2019 2-3 weeks 
 after Generic blogposts
 about all the things
 announced Generic blogpost
 about what is 
 Jetpack Compose Specific blogpost
 about Jetpack
 Compose End of the excitement
 around Jetpack 
 Compose

Slide 14

Slide 14 text

luca_nicolett JETPACK COMPOSE Android Dev 
 Summit 
 Oct 2019 2-3 weeks 
 after

Slide 15

Slide 15 text

luca_nicolett JETPACK COMPOSE Android Dev 
 Summit 
 Oct 2019 2-3 weeks 
 after Some conversations on the kotlinlang slack channel

Slide 16

Slide 16 text

luca_nicolett What’s that? ๏ Declarative UI JETPACK COMPOSE

Slide 17

Slide 17 text

luca_nicolett Declarative → describe what you would like Imperative → describe how to achieve it JETPACK COMPOSE Declarative
 A tower of 3 blocks. Imperative
 1. Put down first block
 2. Put down second block
 3. Put down third block

Slide 18

Slide 18 text

luca_nicolett ANDROID - OLD

Slide 19

Slide 19 text

luca_nicolett Column( children: [ Text('First block'), Text('Second block'), Text('Third block’) ] ) FLUTTER

Slide 20

Slide 20 text

luca_nicolett Column( crossAxisAlignment = Center ) { Text("First block") Text("Second block") Text("Third block") } JETPACK COMPOSE

Slide 21

Slide 21 text

luca_nicolett What’s that? ๏ Declarative UI ๏ Concise & idiomatic ๏ Components ๏ Recomposition ๏ Compatible JETPACK COMPOSE

Slide 22

Slide 22 text

luca_nicolett @GenerateView @Composable fun Greetings(name: String) { /* ... */ } val greetingsView = findViewById(R.id.greetings) greetingsView.name = "Luca" JETPACK COMPOSE

Slide 23

Slide 23 text

luca_nicolett @GenerateView @Composable fun Greetings(name: String) { /* ... */ } val greetingsView = findViewById(R.id.greetings) greetingsView.name = "Luca" JETPACK COMPOSE

Slide 24

Slide 24 text

luca_nicolett @GenerateView @Composable fun Greetings(name: String) { /* ... */ } val greetingsView = findViewById(R.id.greetings) greetingsView.name = "Luca" JETPACK COMPOSE

Slide 25

Slide 25 text

luca_nicolett @GenerateView @Composable fun Greetings(name: String) { /* ... */ } val greetingsView = findViewById(R.id.greetings) greetingsView.name = "Luca" JETPACK COMPOSE

Slide 26

Slide 26 text

luca_nicolett What’s that? ๏ Declarative UI ๏ Concise & idiomatic ๏ Components ๏ Recomposition ๏ Compatible ๏ Unbundled from the OS JETPACK COMPOSE

Slide 27

Slide 27 text

luca_nicolett 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" } JETPACK COMPOSE

Slide 28

Slide 28 text

luca_nicolett buildscript { ... dependencies { classpath "org.android.tools.build:gradle:4.0.0-alpha01" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2" } } JETPACK COMPOSE

Slide 29

Slide 29 text

luca_nicolett dependencies { // Include the following Compose toolkit dependencies. implementation "androidx.ui:ui-framework:0.1.0-dev02" implementation "androidx.ui:ui-tooling:0.1.0-dev02" implementation "androidx.ui:ui-layout:0.1.0-dev02" implementation "androidx.ui:ui-material:0.1.0-dev02" } JETPACK COMPOSE

Slide 30

Slide 30 text

luca_nicolett dependencies { impl "androidx.compose:compose-runtime:0.1.0-dev02" } JETPACK COMPOSE

Slide 31

Slide 31 text

luca_nicolett JETPACK COMPOSE

Slide 32

Slide 32 text

luca_nicolett mkdir ~/bin PATH=~/bin:$PATH curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo chmod a+x ~/bin/repo JETPACK COMPOSE

Slide 33

Slide 33 text

luca_nicolett mkdir androidx-master-dev cd androidx-master-dev repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev repo sync -j8 -c JETPACK COMPOSE

Slide 34

Slide 34 text

luca_nicolett mkdir androidx-master-dev cd androidx-master-dev repo init -u https://android.googlesource.com/platform/manifest -b androidx-master-dev repo sync -j8 -c Download the code (and grab a coffee while we pull down 6GB) JETPACK COMPOSE

Slide 35

Slide 35 text

luca_nicolett cd path/to/checkout/frameworks/support/ ./studiow JETPACK COMPOSE

Slide 36

Slide 36 text

luca_nicolett class MyActivity: Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyComposableFunction() } } } JETPACK COMPOSE

Slide 37

Slide 37 text

luca_nicolett class MyActivity: Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyComposableFunction() } } } JETPACK COMPOSE

Slide 38

Slide 38 text

luca_nicolett fun Activity.setContent(content: @Composable() () -> Unit) : CompositionContext? { val craneView = window.decorView .findViewById(android.R.id.content) .getChildAt(0) as? AndroidCraneView ?: AndroidCraneView(this) .also { setContentView(it) } val coroutineContext = Dispatchers.Main return Compose.composeInto(craneView.root, this) { WrapWithAmbients( craneView, this, coroutineContext JETPACK COMPOSE

Slide 39

Slide 39 text

luca_nicolett fun Activity.setContent(content: @Composable() () -> Unit) : CompositionContext? { val craneView = window.decorView .findViewById(android.R.id.content) .getChildAt(0) as? AndroidCraneView ?: AndroidCraneView(this) .also { setContentView(it) } val coroutineContext = Dispatchers.Main return Compose.composeInto(craneView.root, this) { WrapWithAmbients( craneView, this, coroutineContext JETPACK COMPOSE

Slide 40

Slide 40 text

luca_nicolett fun Activity.setContent(content: @Composable() () -> Unit) : CompositionContext? { val craneView = window.decorView .findViewById(android.R.id.content) .getChildAt(0) as? AndroidCraneView ?: AndroidCraneView(this) .also { setContentView(it) } val coroutineContext = Dispatchers.Main return Compose.composeInto(craneView.root, this) { WrapWithAmbients( craneView, this, coroutineContext JETPACK COMPOSE

Slide 41

Slide 41 text

luca_nicolett : CompositionContext? { val craneView = window.decorView .findViewById(android.R.id.content) .getChildAt(0) as? AndroidCraneView ?: AndroidCraneView(this) .also { setContentView(it) } val coroutineContext = Dispatchers.Main return Compose.composeInto(craneView.root, this) { WrapWithAmbients( craneView, this, coroutineContext ) { content() } } } JETPACK COMPOSE

Slide 42

Slide 42 text

luca_nicolett : CompositionContext? { val craneView = window.decorView .findViewById(android.R.id.content) .getChildAt(0) as? AndroidCraneView ?: AndroidCraneView(this) .also { setContentView(it) } val coroutineContext = Dispatchers.Main return Compose.composeInto(craneView.root, this) { WrapWithAmbients( craneView, this, coroutineContext ) { content() } } } JETPACK COMPOSE

Slide 43

Slide 43 text

luca_nicolett @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } JETPACK COMPOSE

Slide 44

Slide 44 text

luca_nicolett @Preview @Composable fun Greetings() { Text("Hello Mobile Unplugged”) } JETPACK COMPOSE

Slide 45

Slide 45 text

luca_nicolett JETPACK COMPOSE

Slide 46

Slide 46 text

luca_nicolett @Composable fun Greetings(text: String) { Text("Hello $text") } @Preview @Composable fun GreetMobileUnplugged() { Greetings(text = “Mobile Unplugged”) } JETPACK COMPOSE

Slide 47

Slide 47 text

luca_nicolett @Preview("Dark Colors") @Composable fun GreetMobileUnplugged() { MaterialTheme(colors = darkThemeColors) { Surface { Greetings(text = "Mobile Unplugged") } } } JETPACK COMPOSE

Slide 48

Slide 48 text

luca_nicolett /** * A [FileEditor] that displays a preview of composable * elements defined in the given [psiFile]. * * The editor will display previews for all declared * `@Composable` functions that also use the `@Preview` * (see [PREVIEW_ANNOTATION_FQN])annotation. * For every preview element a small XML is generated * that allows Layoutlib to render a `@Composable` functions. * * @param psiFile [PsiFile] pointing to the Kotlin source * containing the code to preview. * @param previewProvider call to obtain the [PreviewElement]s * from the file. */ JETPACK COMPOSE

Slide 49

Slide 49 text

luca_nicolett @Composable fun Text(/* ... */) { /* ... */ Draw { canvas, _ -> internalSelection.value?.let { textDelegate.paintBackground( it.min, it.max, selectionColor, canvas ) } textDelegate.paint(canvas) // Paints the text onto the given canvas. } /* ... */ } JETPACK COMPOSE

Slide 50

Slide 50 text

luca_nicolett @Composable fun Text(/* ... */) { /* ... */ Draw { canvas, _ -> internalSelection.value?.let { textDelegate.paintBackground( it.min, it.max, selectionColor, canvas ) } textDelegate.paint(canvas) // Paints the text onto the given canvas. } /* ... */ } JETPACK COMPOSE

Slide 51

Slide 51 text

luca_nicolett @Composable fun Text(/* ... */) { /* ... */ Draw { canvas, _ -> internalSelection.value?.let { textDelegate.paintBackground( it.min, it.max, selectionColor, canvas ) } textDelegate.paint(canvas) // Paints the text onto the given canvas. } /* ... */ } JETPACK COMPOSE

Slide 52

Slide 52 text

luca_nicolett JETPACK COMPOSE

Slide 53

Slide 53 text

luca_nicolett JETPACK COMPOSE

Slide 54

Slide 54 text

luca_nicolett JETPACK COMPOSE

Slide 55

Slide 55 text

luca_nicolett @Composable fun TextField(/* ... */) { // States val hasFocus = +state { false } val coords = +state { null } val inputSession = +state { NO_SESSION } /* ... */ } JETPACK COMPOSE

Slide 56

Slide 56 text

luca_nicolett @CheckResult("+") /*inline*/ fun state(/*crossinline*/ init: () -> T) = memo { State(init()) } JETPACK COMPOSE

Slide 57

Slide 57 text

luca_nicolett /** * The State class is an @Model class meant to * wrap around a single value. * It is used in the `+state` and `+stateFor` effects. */ @Model class State @PublishedApi internal constructor(value: T) : Framed {} JETPACK COMPOSE

Slide 58

Slide 58 text

luca_nicolett hasFocus.value = false JETPACK COMPOSE

Slide 59

Slide 59 text

luca_nicolett @Composable fun Counter() { var count by +state { 0 } Text(text = "You clicked $count times") Button("Click me",{ count = count + 1 }) } JETPACK COMPOSE

Slide 60

Slide 60 text

luca_nicolett @Composable fun Counter() { var count by +state { 0 } Text(text = "You clicked $count times") Button("Click me",{ count = count + 1 }) } JETPACK COMPOSE

Slide 61

Slide 61 text

luca_nicolett @Composable fun Counter() { var count by +state { 0 } Text(text = "You clicked $count times") Button("Click me",{ count = count + 1 }) } JETPACK COMPOSE

Slide 62

Slide 62 text

luca_nicolett @Composable fun Counter() { var count by +state { 0 } Text(text = "You clicked $count times") Button("Click me",{ count = count + 1 }) } JETPACK COMPOSE

Slide 63

Slide 63 text

luca_nicolett /** * [Model] can be applied to a class which represents your * application's data model, and will cause instances of the * class to become observable, such that a read of a property * of an instance of this class during the invocation of a * composable function will cause that component to be * "subscribed" to mutations of that instance. Composable * functions which directly or indirectly read properties * of the model class, the composables will be recomposed * whenever any properties of the the model are written to. */ JETPACK COMPOSE

Slide 64

Slide 64 text

luca_nicolett @Model data class TaskModel( var isDone: Boolean, val description: String ) JETPACK COMPOSE

Slide 65

Slide 65 text

luca_nicolett @Model data class TaskModel( var isDone: Boolean, val description: String ): BaseModel() JETPACK COMPOSE

Slide 66

Slide 66 text

luca_nicolett @Model data class TaskModel( var isDone: Boolean, val description: String ): BaseModel() TaskModel.kt: (14, 3): Model objects do not support inheritance JETPACK COMPOSE

Slide 67

Slide 67 text

luca_nicolett JETPACK COMPOSE

Slide 68

Slide 68 text

luca_nicolett RawDragGestureDetector(DragObserver { distance -> //update animation value }) { PressGestureDetector({ position -> // animate to position }) { Container(60.dp, expanded = true) { DrawSeekBar(animValue.value) } } } JETPACK COMPOSE

Slide 69

Slide 69 text

luca_nicolett RawDragGestureDetector(DragObserver { distance -> //update animation value }) { PressGestureDetector({ position -> // animate to position }) { Container(60.dp, expanded = true) { DrawSeekBar(animValue.value) } } } JETPACK COMPOSE

Slide 70

Slide 70 text

luca_nicolett RawDragGestureDetector(DragObserver { distance -> //update animation value }) { PressGestureDetector({ position -> // animate to position }) { Container(60.dp, expanded = true) { DrawSeekBar(animValue.value) } } } JETPACK COMPOSE

Slide 71

Slide 71 text

luca_nicolett RawDragGestureDetector(DragObserver { distance -> //update animation value }) { PressGestureDetector({ position -> // animate to position }) { Container(60.dp, expanded = true) { DrawSeekBar(animValue.value) } } } JETPACK COMPOSE

Slide 72

Slide 72 text

luca_nicolett @Composable fun DrawSeekBar(x: Float) { var paint = +memo { Paint() } Draw { canvas, parentSize -> /* ... */ canvas.drawRect(Rect(/* ... */), paint) canvas.drawRect(Rect(/* ... */), paint) canvas.drawCircle(/* ... */, paint) } } JETPACK COMPOSE

Slide 73

Slide 73 text

luca_nicolett @Composable fun DrawSeekBar(x: Float) { var paint = +memo { Paint() } Draw { canvas, parentSize -> /* ... */ canvas.drawRect(Rect(/* ... */), paint) canvas.drawRect(Rect(/* ... */), paint) canvas.drawCircle(/* ... */, paint) } } JETPACK COMPOSE

Slide 74

Slide 74 text

luca_nicolett JETPACK COMPOSE

Slide 75

Slide 75 text

luca_nicolett JETPACK COMPOSE @Composable fun RippleRect() { val radius = withDensity(+ambientDensity()) { TargetRadius.toPx() } val toState = +state { ButtonStatus.Initial } val rippleTransDef = +memo { createTransDef(radius.value) } val onPress: (PxPosition) -> Unit = { p -> down.x = p.x.value down.y = p.y.value toState.value = ButtonStatus.Pressed }

Slide 76

Slide 76 text

luca_nicolett TargetRadius.toPx() } val toState = +state { ButtonStatus.Initial } val rippleTransDef = +memo { createTransDef(radius.value) } val onPress: (PxPosition) -> Unit = { p -> down.x = p.x.value down.y = p.y.value toState.value = ButtonStatus.Pressed } val onRelease: () -> Unit = { toState.value = ButtonStatus.Released } PressGestureDetector(onPress, onRelease) { Container(true) { Transition( JETPACK COMPOSE

Slide 77

Slide 77 text

luca_nicolett JETPACK COMPOSE down.y = p.y.value toState.value = ButtonStatus.Pressed } val onRelease: () -> Unit = { toState.value = ButtonStatus.Released } PressGestureDetector(onPress, onRelease) { Container(true) { Transition( definition = rippleTransDef, toState = toState.value ) { state -> RippleRectFromState(state = state) } } } }

Slide 78

Slide 78 text

luca_nicolett JETPACK COMPOSE down.y = p.y.value toState.value = ButtonStatus.Pressed } val onRelease: () -> Unit = { toState.value = ButtonStatus.Released } PressGestureDetector(onPress, onRelease) { Container(true) { Transition( definition = rippleTransDef, toState = toState.value ) { state -> RippleRectFromState(state = state) } } } }

Slide 79

Slide 79 text

luca_nicolett JETPACK COMPOSE @Composable fun RippleRectFromState(state: TransitionState) { // TODO: file bug for when "down" is not a // file level val, it's not memoized correctly val x = down.x val y = down.y val paint = Paint().apply { color = Color( alpha = getAlpha(), red = 0, green = 235,

Slide 80

Slide 80 text

luca_nicolett JETPACK COMPOSE // file level val, it's not memoized correctly val x = down.x val y = down.y val paint = Paint().apply { color = Color( alpha = getAlpha(), red = 0, green = 235, blue = 224 ) } val radius = state[radius] Draw { canvas, _ ->

Slide 81

Slide 81 text

luca_nicolett JETPACK COMPOSE red = 0, green = 235, blue = 224 ) } val radius = state[radius] Draw { canvas, _ -> canvas.drawCircle( Offset(x, y), radius, paint ) } }

Slide 82

Slide 82 text

luca_nicolett JETPACK COMPOSE

Slide 83

Slide 83 text

luca_nicolett JETPACK COMPOSE @Composable fun AlertDialog( onCloseRequest: () -> Unit, title: (@Composable() () -> Unit)? = null, text: (@Composable() () -> Unit), buttons: @Composable() () -> Unit ) { val currentColors = +ambient(Colors) val currentTypography = +ambient(Typography) Dialog(onCloseRequest = onCloseRequest) { /* ... */ } }

Slide 84

Slide 84 text

luca_nicolett JETPACK COMPOSE @Composable fun Dialog( onCloseRequest: () -> Unit, children: @Composable() () -> Unit ) { val context = +ambient(ContextAmbient) val dialog = +memo { DialogWrapper(context, onCloseRequest) } +onActive { dialog.show()

Slide 85

Slide 85 text

luca_nicolett JETPACK COMPOSE @Composable fun Dialog( onCloseRequest: () -> Unit, children: @Composable() () -> Unit ) { val context = +ambient(ContextAmbient) val dialog = +memo { DialogWrapper(context, onCloseRequest) } +onActive { dialog.show()

Slide 86

Slide 86 text

luca_nicolett JETPACK COMPOSE ) { val context = +ambient(ContextAmbient) val dialog = +memo { DialogWrapper(context, onCloseRequest) } +onActive { dialog.show() onDispose { dialog.dismiss() dialog.disposeComposition() } } +onCommit { dialog.setContent(children)

Slide 87

Slide 87 text

luca_nicolett JETPACK COMPOSE ) { val context = +ambient(ContextAmbient) val dialog = +memo { DialogWrapper(context, onCloseRequest) } +onActive { dialog.show() onDispose { dialog.dismiss() dialog.disposeComposition() } } +onCommit { dialog.setContent(children)

Slide 88

Slide 88 text

luca_nicolett JETPACK COMPOSE

Slide 89

Slide 89 text

luca_nicolett JETPACK COMPOSE ) { val context = +ambient(ContextAmbient) val dialog = +memo { DialogWrapper(context, onCloseRequest) } +onActive { dialog.show() onDispose { dialog.dismiss() dialog.disposeComposition() } } +onCommit { dialog.setContent(children)

Slide 90

Slide 90 text

luca_nicolett JETPACK COMPOSE +onActive { dialog.show() onDispose { dialog.dismiss() dialog.disposeComposition() } } +onCommit { dialog.setContent(children) } }

Slide 91

Slide 91 text

luca_nicolett JETPACK COMPOSE import android.app.Dialog private class DialogWrapper( context: Context, val onCloseRequest: () -> Unit ) : Dialog(context) { /* ... */ }

Slide 92

Slide 92 text

luca_nicolett @Composable fun Padding( padding: EdgeInsets, children: @Composable() () -> Unit ) { /* ... */ } JETPACK COMPOSE

Slide 93

Slide 93 text

luca_nicolett Padding(16.dp) { Text("Hello ") } JETPACK COMPOSE

Slide 94

Slide 94 text

luca_nicolett data class PaddingModifier( val left: IntPx = 0.ipx, val top: IntPx = 0.ipx, val right: IntPx = 0.ipx, val bottom: IntPx = 0.ipx ) : LayoutModifier { /* ... */ } JETPACK COMPOSE

Slide 95

Slide 95 text

luca_nicolett /** * An immutable chain of [modifier elements][Modifier.Element] * for use with Composables. A Composable that has a `Modifier` * can be considered decorated or wrapped by that `Modifier`. * * Composables that accept a [Modifier] as a parameter to be * applied to the whole component represented by the composable * function should name the parameter `modifier` and assign the * parameter a default value of [Modifier.None] */ JETPACK COMPOSE

Slide 96

Slide 96 text

luca_nicolett data class PaddingModifier() Text( text = "Hello ", modifier = PaddingModifier(16.dp) ) JETPACK COMPOSE

Slide 97

Slide 97 text

luca_nicolett Text( text = "Hello ", modifier = PaddingModifier(16.dp) ) JETPACK COMPOSE Padding(16.dp) { Text("Hello ") } VS

Slide 98

Slide 98 text

luca_nicolett JETPACK COMPOSE Padding(16.dp) { Text("Hello ”) Text("Hello ") }

Slide 99

Slide 99 text

luca_nicolett override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { /* ... */ } } JETPACK COMPOSE

Slide 100

Slide 100 text

luca_nicolett fun CustomTheme(body: @Composable() () -> Unit) { val colors = MaterialColors( primary = Color(0xFFDD0D3C), primaryVariant = Color(0xFFC20029), secondary = Color(0xFF00AD3C), /* other colors */ ) MaterialTheme (colors = colors) { body() } } JETPACK COMPOSE

Slide 101

Slide 101 text

luca_nicolett override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CustomTheme { TopAppBar( title = { Text("Exploring Compose") } ) /* ... */ } } } JETPACK COMPOSE

Slide 102

Slide 102 text

luca_nicolett JETPACK COMPOSE

Slide 103

Slide 103 text

luca_nicolett #6200EE #3700B3 #03DAC5 JETPACK COMPOSE

Slide 104

Slide 104 text

luca_nicolett <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> JETPACK COMPOSE

Slide 105

Slide 105 text

luca_nicolett </resources> JETPACK COMPOSE

Slide 106

Slide 106 text

luca_nicolett JETPACK COMPOSE

Slide 107

Slide 107 text

luca_nicolett <item name="android:windowTranslucentStatus">true</item> <item name="android:statusBarColor">@android:color/white</item> <item name="android:windowTranslucentNavigation">true</item> <item name="android:fitsSystemWindows">true</item> JETPACK COMPOSE

Slide 108

Slide 108 text

luca_nicolett JETPACK COMPOSE

Slide 109

Slide 109 text

luca_nicolett override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CustomTheme { Column { ColoredRect(Color.Transparent, height = 24.dp) TopAppBar(title = { Text("Exploring Compose") } } } } } JETPACK COMPOSE

Slide 110

Slide 110 text

luca_nicolett override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CustomTheme { Column { ColoredRect(Color.Transparent, height = 24.dp) TopAppBar(title = { Text("Exploring Compose") } } } } } JETPACK COMPOSE

Slide 111

Slide 111 text

luca_nicolett JETPACK COMPOSE

Slide 112

Slide 112 text

luca_nicolett ColoredRect(+themeColor { primaryVariant }, height = 24.dp) JETPACK COMPOSE

Slide 113

Slide 113 text

luca_nicolett JETPACK COMPOSE

Slide 114

Slide 114 text

luca_nicolett JETPACK COMPOSE

Slide 115

Slide 115 text

luca_nicolett JETPACK COMPOSE

Slide 116

Slide 116 text

luca_nicolett JETPACK COMPOSE

Slide 117

Slide 117 text

luca_nicolett JETPACK COMPOSE

Slide 118

Slide 118 text

luca_nicolett JETPACK COMPOSE

Slide 119

Slide 119 text

luca_nicolett JETPACK COMPOSE

Slide 120

Slide 120 text

luca_nicolett JETPACK COMPOSE

Slide 121

Slide 121 text

luca_nicolett import androidx.compose.Model import androidx.compose.composer import androidx.compose.frames.ModelList JETPACK COMPOSE

Slide 122

Slide 122 text

luca_nicolett Compose UI. Compose Runtime. JETPACK COMPOSE

Slide 123

Slide 123 text

luca_nicolett - https://android-developers.googleblog.com/2019/10/android-dev-summit-2019-keynote.html
 https://blog.karumi.com/android-jetpack-compose-review/ - https://blog.karumi.com/android-jetpack-compose-review/ - https://android.jlelse.eu/jetpack-compose-primer-92ff005b7ce2 - https://developer.android.com/jetpack/compose/tutorial - https://www.youtube.com/watch?v=VsStyq4Lzxo - https://medium.com/q42-engineering/android-jetpack-compose-895b7fd04bf4 - https://blog.karumi.com/android-jetpack-compose-review - https://courses.csail.mit.edu/6.831/2006/lectures/L9.pdf - http://intelligiblebabble.com/compose-from-first-principles/ - http://intelligiblebabble.com/content-on-declarative-ui/ - https://www.youtube.com/watch? v=Q9MtlmmN4Q0&list=PLWz5rJ2EKKc_xXXubDti2eRnIKU0p7wHd&index=60 - https://www.youtube.com/watch? v=SPsdRXcgqjI&list=PLWz5rJ2EKKc_xXXubDti2eRnIKU0p7wHd&index=8&t=0s - https://www.youtube.com/watch? v=XPMrnR1_Biw&list=PLWz5rJ2EKKc_xXXubDti2eRnIKU0p7wHd&index=13&t=0s RESOURCES

Slide 124

Slide 124 text

luca_nicolett THANK YOU! POWERED BY BABYLON HEALTH