Jetpack Compose

Oct 11 2022 · Kotlin 1.7.10, Android 13, Android Studio Chipmunk

Part 1: Jetpack Compose Basics

05. Decouple Composables

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 04. Add State to Composables Next episode: 06. Build Common UI Components - Part 1

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 05. Decouple Composables

In ui/addBook/AddBookActivity, within AddBookTopBar() composable function, the method onBackPressed() is deprecated and is replaced by onBackPressedDispatcher.onBackPressed() method.

In ui/composeUi/InputField, the statement backgroundColor = Color.White is added to make the background color of OutlinedTextField as white instead of the default theme color.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

Demo

One of the most important things about writing good and clean code is decoupling different components, to make them more reusable.

@Composable
@Preview
fun ActionButton(
  modifier: Modifier = Modifier,
  text: String = "Librarian",
  isEnabled: Boolean = true,
  enabledColor: Color = colorResource(id = R.color.colorPrimary),
  disabledTextColor: Color = Color.Gray,
  onClick: () -> Unit = {}
) {

}
  val backgroundColor = if (isEnabled) enabledColor else Color.LightGray

  TextButton(
    shape = RoundedCornerShape(16.dp),
    enabled = isEnabled,
    colors = ButtonDefaults.textButtonColors(
      backgroundColor = backgroundColor,
      contentColor = Color.White,
      disabledContentColor = disabledTextColor
    ),
    modifier = modifier
      .padding(16.dp),
    content = { Text(text = text) },
    onClick = onClick
  )
@Composable
@Preview
fun BackButton(
  modifier: Modifier = Modifier,
  onBackAction: () -> Unit = {}
) {
  IconButton(
    modifier = modifier,
    content = {
      Icon(
        Icons.Default.ArrowBack,
        tint = Color.White,
        contentDescription = "Back"
      )
    },
    onClick = { onBackAction() }
  )
} 
@Composable
@Preview
fun InputField(
  modifier: Modifier = Modifier,
  value: String = "",
  label: String = stringResource(id = R.string.app_name),
  keyboardType: KeyboardType = KeyboardType.Text,
  isInputValid: Boolean = true,
  imeAction: ImeAction = ImeAction.Next,
  onStateChanged: (String) -> Unit = {}
) {
  val focusedColor = colorResource(id = R.color.colorPrimary)
  val unfocusedColor = colorResource(id = R.color.colorPrimaryDark)

}
  OutlinedTextField(
    value = value,
    onValueChange = { newValue -> onStateChanged(newValue) },
    label = { Text(label) },
    modifier = modifier
      .fillMaxWidth()
      .padding(
        start = 16.dp,
        end = 16.dp,
        top = 4.dp,
        bottom = 4.dp
      ),
    keyboardOptions = KeyboardOptions(keyboardType = keyboardType, imeAction = imeAction),
    visualTransformation = getVisualTransformation(keyboardType),
    isError = !isInputValid,
    colors = ...
  )
colors = TextFieldDefaults.textFieldColors(
      focusedIndicatorColor = focusedColor,
      focusedLabelColor = focusedColor,
      unfocusedIndicatorColor = unfocusedColor,
      unfocusedLabelColor = unfocusedColor,
      cursorColor = focusedColor,
      backgroundColor = Color.White    
    )
private fun getVisualTransformation(keyboardType: KeyboardType) =
  if (keyboardType == KeyboardType.Password || keyboardType == KeyboardType.NumberPassword)
    PasswordVisualTransformation()
  else VisualTransformation.None
@Composable
@Preview
fun TopBar(
  modifier: Modifier = Modifier,
  title: String = "Add a new review",
  actions: @Composable RowScope.() -> Unit = {},
  onBackPressed: (() -> Unit)? = null
) {

}
  val backButtonAction: (@Composable () -> Unit)? = if (onBackPressed != null) {
    @Composable { BackButton(onBackAction = { onBackPressed() }) }
  } else {
    null
  }
  TopAppBar(
    modifier = modifier,
    title = { Text(title) },
    navigationIcon = backButtonAction,
    actions = actions,
    backgroundColor = colorResource(id = R.color.colorPrimary),
    contentColor = Color.White
  )
@Composable
fun AddBookTopBar() {
  TopBar(
    title = stringResource(id = R.string.add_book_title),
    onBackPressed = { onBackPressedDispatcher.onBackPressed() })
}
      InputField(
        value = bookNameState.value,
        onStateChanged = { newValue ->
          bookNameState.value = newValue
          _addBookState.value = _addBookState.value?.copy(name = newValue)
        },
        label = stringResource(id = R.string.book_title_hint)
      )

      InputField(
        value = bookDescriptionState.value,
        onStateChanged = { newValue ->
          bookDescriptionState.value = newValue
          _addBookState.value = _addBookState.value?.copy(description = newValue)
        },
        label = stringResource(id = R.string.book_description_hint)
      )

      ActionButton(
        text = stringResource(id = R.string.add_book_button_text),
        onClick = { onAddBookTapped() }
      )
  @Composable
  fun BooksTopBar() {
    TopBar(
      title = stringResource(id = R.string.my_books_title),
      actions = { FilterButton() })
  }

  @Composable
  fun FilterButton() {
    IconButton(onClick = {
      // TODO
    }) {
      Icon(Icons.Default.Edit, tint = Color.White, contentDescription = "Filter")
    }
  }