Successfully reported this slideshow.
Your SlideShare is downloading. ×

Compose Camp - Jetpack Compose for Android Developers Introduction Session Deck.pdf

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 120 Ad

More Related Content

Recently uploaded (20)

Advertisement

Compose Camp - Jetpack Compose for Android Developers Introduction Session Deck.pdf

  1. 1. This work is licensed under the Apache 2.0 License Jetpack Compose for Android Developers
  2. 2. This work is licensed under the Apache 2.0 License Whiston Borja Android Developer Camp leaders
  3. 3. This work is licensed under the Apache 2.0 License ● Thinking in Compose ● Composable functions ● Compose toolkit ● Tooling Agenda
  4. 4. This work is licensed under the Apache 2.0 License Thinking in Compose
  5. 5. This work is licensed under the Apache 2.0 License Construct UI by describing what, not how.
  6. 6. This work is licensed under the Apache 2.0 License goo.gle/compose-samples
  7. 7. This work is licensed under the Apache 2.0 License
  8. 8. This work is licensed under the Apache 2.0 License Survey answer Image Text Radio button
  9. 9. This work is licensed under the Apache 2.0 License <LinearLayout android:orientation=“horizontal” > <ImageView android:id=”@+id/answer_image” ... /> <TextView android:id=”@+id/answer_text” ... /> <RadioButton android:id=”@+id/answer_radio_button” ... /> </LinearLayout> <!-- survey_answer.xml -->
  10. 10. This work is licensed under the Apache 2.0 License class SurveyQuestionActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val image = findViewById(R.id.answer_image) val text = findViewById(R.id.answer_text) val radioButton = findViewById(R.id.answer_radio_button) // ... } } // SurveyQuestionActivity.kt
  11. 11. This work is licensed under the Apache 2.0 License class SurveyQuestionActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { // ... image.setImage(...) text.setText(...) // ... } } // SurveyQuestionActivity.kt
  12. 12. This work is licensed under the Apache 2.0 License
  13. 13. This work is licensed under the Apache 2.0 License
  14. 14. This work is licensed under the Apache 2.0 License
  15. 15. This work is licensed under the Apache 2.0 License
  16. 16. This work is licensed under the Apache 2.0 License
  17. 17. This work is licensed under the Apache 2.0 License Survey answer Image Text Radio button
  18. 18. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { Image(answer.image) Text(answer.text) RadioButton(false, onClick = { /* … */ }) } } // SurveyAnswer.kt
  19. 19. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { Image(answer.image) Text(answer.text) RadioButton(false, onClick = { /* … */ }) } } // SurveyAnswer.kt
  20. 20. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { Image(answer.image) Text(answer.text) RadioButton(false, onClick = { /* … */ }) } } // SurveyAnswer.kt
  21. 21. This work is licensed under the Apache 2.0 License Construct UI by describing what, not how.
  22. 22. This work is licensed under the Apache 2.0 License Event handler UI element onClick()
  23. 23. This work is licensed under the Apache 2.0 License UI State
  24. 24. This work is licensed under the Apache 2.0 License UI 2 State 2
  25. 25. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { / * ... */ var selected: Boolean = // ... RadioButton(selected, onClick = { /* … */ }) } } // SurveyAnswer.kt
  26. 26. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { / * ... */ var selected: Boolean = // ... RadioButton(selected, onClick = { selected = !selected }) } } // SurveyAnswer.kt
  27. 27. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { / * ... */ var selected: Boolean = // ... RadioButton(selected, onClick = { selected = !selected }) } } // SurveyAnswer.kt
  28. 28. Describe what, not how UI elements are functions State controls UI Events control State 1 2 3 4
  29. 29. This work is licensed under the Apache 2.0 License Composable functions
  30. 30. This work is licensed under the Apache 2.0 License goo.gle/compose-samples
  31. 31. This work is licensed under the Apache 2.0 License
  32. 32. This work is licensed under the Apache 2.0 License // SurveyAnswer.kt @Composable fun SurveyAnswer(answer: Answer) { Row { Image(answer.image) Text(answer.text) RadioButton(false, onClick = { /* … */ }) } }
  33. 33. This work is licensed under the Apache 2.0 License // SurveyAnswer.kt @Composable fun SurveyAnswer(answer: Answer) { Row { Image(answer.image) Text(answer.text) RadioButton(false, onClick = { /* … */ }) } }
  34. 34. This work is licensed under the Apache 2.0 License // SurveyAnswer.kt @Composable fun SurveyAnswer(answer: Answer) { /* … */ } @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { answers.forEach { answer -> SurveyAnswer(answer = answer) } } }
  35. 35. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { answers.forEach { answer -> SurveyAnswer(answer = answer) } } }
  36. 36. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { answers.forEach { answer -> SurveyAnswer(answer = answer) } } }
  37. 37. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt
  38. 38. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { answers.forEach { answer -> // Can’t do this!! val answer = SurveyAnswer(answer = answer) } } }
  39. 39. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { answers.forEach { answer -> SurveyAnswer(answer = answer) } } }
  40. 40. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { if (answers.isEmpty()) { Text(“There are no answers to choose from!”) } else { answers.forEach { answer -> SurveyAnswer(answer = answer) } } } }
  41. 41. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { // Don’t do this! There shouldn’t be side-effects SurveyApp.didShowSingleChoiceQuestion = true Column { if (answers.isEmpty()) { /* ... */ } else { /* ... */ } } }
  42. 42. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { // Fast and no side-effects Column { if (answers.isEmpty()) { /* ... */ } else { /* ... */ } } }
  43. 43. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { Column { answers.forEach { answer -> SurveyAnswer(answer = answer) } } }
  44. 44. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  45. 45. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  46. 46. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  47. 47. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: Answer? = null answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  48. 48. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: Answer? = null answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  49. 49. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: MutableState<Answer?> = mutableStateOf(null) answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  50. 50. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: MutableState<Answer?> = mutableStateOf(null) answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = false, ) } }
  51. 51. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: MutableState<Answer?> = mutableStateOf(null) answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer.state == answer), ) } }
  52. 52. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: MutableState<Answer?> = remember { mutableStateOf(null) } answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer.state == answer), ) } }
  53. 53. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: MutableState<Answer?> = rememberSaveable { mutableStateOf(null) } answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer.state == answer), ) } }
  54. 54. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: Answer? by rememberSaveable { mutableStateOf(null) } answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer.state == answer), ) } }
  55. 55. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: Answer? by rememberSaveable { mutableStateOf(null) } answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer == answer), ) } }
  56. 56. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { var selectedAnswer: Answer? by rememberSaveable { mutableStateOf(null) } answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer == answer), onAnswerSelected = { answer -> selectedAnswer = answer } ) } }
  57. 57. This work is licensed under the Apache 2.0 License Event handler UI element event state Events change State
  58. 58. This work is licensed under the Apache 2.0 License Event handler UI element onAnswerSelecte d answer Events change State
  59. 59. This work is licensed under the Apache 2.0 License // SingleChoiceQuestion.kt @Composable fun SingleChoiceQuestion(answers: List<Answer>) { val selectedAnswer: Answer? by rememberSaveable { mutableStateOf<Answer>(null) } answers.forEach { answer -> SurveyAnswer( answer = answer, isSelected = (selectedAnswer == answer), onAnswerSelected = { answer -> selectedAnswer = answer } ) } }
  60. 60. This work is licensed under the Apache 2.0 License Composable functions can execute in any order.
  61. 61. This work is licensed under the Apache 2.0 License // ButtonRow.kt @Composable fun ButtonRow() { MyFancyNavigation { StartScreen() MiddleScreen() EndScreen() } }
  62. 62. This work is licensed under the Apache 2.0 License Composable functions can run in parallel.
  63. 63. This work is licensed under the Apache 2.0 License @Composable fun ListComposable(myList: List<String>) { Row(horizontalArrangement = Arrangement.SpaceBetween) { Column { for (item in myList) { Text("Item: $item") } } Text("Count: ${myList.size}") } } // ListComposable.kt
  64. 64. This work is licensed under the Apache 2.0 License @Composable fun ListWithBug(myList: List<String>) { var items = 0 Row(horizontalArrangement = Arrangement.SpaceBetween) { Column { for (item in myList) { Text("Item: $item”) items++ // Avoid! Side-effect of the column recomposing. } } Text("Count: $items") } } // ListComposable.kt
  65. 65. This work is licensed under the Apache 2.0 License Recomposition skips as much as possible.
  66. 66. This work is licensed under the Apache 2.0 License @Composable fun GreetingScreen(name: String) { Column { Header() Greeting(name = name) Footer() } } // GreenScreen.kt
  67. 67. This work is licensed under the Apache 2.0 License Recomposition is optimistic.
  68. 68. This work is licensed under the Apache 2.0 License Composable functions might run frequently.
  69. 69. This work is licensed under the Apache 2.0 License Summary Create composables using the @Composable annotation It’s quick & easy to create composables Composables accept parameters Use MutableState and remember Composables should be side-effect free
  70. 70. This work is licensed under the Apache 2.0 License Composables can: Execute in any order Run in parallel Be skipped Run frequently 1 2 3 4
  71. 71. This work is licensed under the Apache 2.0 License Compose Toolkit
  72. 72. This work is licensed under the Apache 2.0 License goo.gle/compose-samples
  73. 73. This work is licensed under the Apache 2.0 License
  74. 74. This work is licensed under the Apache 2.0 License
  75. 75. This work is licensed under the Apache 2.0 License MaterialTheme( colorScheme = MyAppsColorScheme, typography = MyAppsTypography, shapes = MyAppsShapes ) { // Content goes here }
  76. 76. This work is licensed under the Apache 2.0 License
  77. 77. This work is licensed under the Apache 2.0 License
  78. 78. This work is licensed under the Apache 2.0 License
  79. 79. This work is licensed under the Apache 2.0 License
  80. 80. This work is licensed under the Apache 2.0 License
  81. 81. This work is licensed under the Apache 2.0 License Scaffold( topBar = { SmallTopAppBar(/* ... */) }, floatingActionButtonPosition = FabPosition.End, floatingActionButton = { FloatingActionButton(/* ... */) }, content = { /* ... */ } )
  82. 82. This work is licensed under the Apache 2.0 License SurveyTopAppBa r SurveyBottomBa r Question
  83. 83. This work is licensed under the Apache 2.0 License
  84. 84. This work is licensed under the Apache 2.0 License
  85. 85. This work is licensed under the Apache 2.0 License
  86. 86. This work is licensed under the Apache 2.0 License
  87. 87. This work is licensed under the Apache 2.0 License
  88. 88. This work is licensed under the Apache 2.0 License Surface { Text("Hello Compose") } Hello Compose
  89. 89. This work is licensed under the Apache 2.0 License Surface( color = MaterialTheme.colorScheme.primary, ) { Text("Hello Compose") } Hello Compose
  90. 90. This work is licensed under the Apache 2.0 License Surface( color = MaterialTheme.colorScheme.primary, shape = RoundedCornerShape(8.dp), ) { Text("Hello Compose") } Hello Compose
  91. 91. This work is licensed under the Apache 2.0 License Surface( color = MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(8.dp), border = BorderStroke(2.dp, MaterialTheme.colorScheme.outline ) ) { Text("Hello Compose") } Hello Compose
  92. 92. This work is licensed under the Apache 2.0 License Surface( color = MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(8.dp), border = BorderStroke(2.dp, MaterialTheme.colorScheme.surfaceVariant ), shadowElevation = 8.dp, tonalElevation = 8.dp, ) { Text("Hello Compose") } Hello Compose
  93. 93. This work is licensed under the Apache 2.0 License
  94. 94. This work is licensed under the Apache 2.0 License
  95. 95. goo.gle/compose-material- ref m3.material.io
  96. 96. This work is licensed under the Apache 2.0 License Standard layouts
  97. 97. This work is licensed under the Apache 2.0 License Row { Component1() Component2() Component3() } 1 2 3 Row
  98. 98. This work is licensed under the Apache 2.0 License 1 2 3 Column Column { Component1() Component2() Component3() }
  99. 99. This work is licensed under the Apache 2.0 License 2 1 3 Box Box { Component1() Component2() Component3() }
  100. 100. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row { Image(answer.image) Text(answer.text) RadioButton(/* … */) } }
  101. 101. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row( verticalAlignment = Alignment.CenterVertically ) { /* ... */ } }
  102. 102. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { /* ... */ } }
  103. 103. goo.gle/compose-layouts-docs
  104. 104. This work is licensed under the Apache 2.0 License Modifiers
  105. 105. This work is licensed under the Apache 2.0 License Text("Hello Compose") Hello Compose
  106. 106. This work is licensed under the Apache 2.0 License Text( "Hello Compose!", Modifier.background(Color.Magenta) ) Hello Compose
  107. 107. This work is licensed under the Apache 2.0 License Text( "Hello Compose!", Modifier.background(Color.Magenta) .size(200.dp, 30.dp) ) Hello Compose
  108. 108. This work is licensed under the Apache 2.0 License Text( "Hello Compose!", Modifier.background(Color.Magenta) .size(200.dp, 30.dp) .padding(5.dp) ) Hello Compose
  109. 109. This work is licensed under the Apache 2.0 License Text( "Hello Compose!", Modifier.background(Color.Magenta) .size(200.dp, 30.dp) .padding(5.dp) .alpha(0.5f) ) Hello Compose
  110. 110. This work is licensed under the Apache 2.0 License Text( "Hello Compose!", Modifier.background(Color.Magenta) .size(200.dp, 30.dp) .padding(5.dp) .alpha(0.5f) .clickable { // Called when Text clicked } ) Hello Compose
  111. 111. This work is licensed under the Apache 2.0 License Box(Modifier.size(150.dp)) { Text("Hello Compose") } Hello Compose
  112. 112. This work is licensed under the Apache 2.0 License Box(Modifier.size(150.dp)) { Text( "Hello Compose!", Modifier.align( Alignment.BottomEnd ) ) } Hello Compose
  113. 113. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row(...) { Image(answer.image) Text(answer.text) RadioButton(/* … */) } } Desired Current
  114. 114. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row( Modifier.fillMaxWidth(), /* ... */ ) { Image(answer.image) Text(answer.text) RadioButton(/* ... */) } } Desired Current
  115. 115. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Row( Modifier.fillMaxWidth() .padding(16.dp), /* ... */ ) { Image(answer.image) Text(answer.text) RadioButton(/* ... */) } } Desired Current
  116. 116. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Surface( border = BorderStroke( 1.dp, MaterialTheme.colorScheme.outline ), shape = MaterialTheme.shapes.small ) { Row(/* ... */) { } } } Desired Current
  117. 117. goo.gle/compose-modifiers goo.gle/compose-modifiers- list
  118. 118. This work is licensed under the Apache 2.0 License @Composable fun SurveyAnswer(answer: Answer) { Surface( border = BorderStroke( 1.dp, MaterialTheme.colorScheme.outline ), shape = MaterialTheme.shapes.small ) { Row(Modifier.fillMaxWidth().padding(16.dp)) { Image(answer.image) Text(answer.text) RadioButton(/* … */) } } }
  119. 119. This work is licensed under the Apache 2.0 License Compose Tooling
  120. 120. This work is licensed under the Apache 2.0 License Live demo!

×