Jetpack Compose

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

Part 1: Jetpack Compose Basics

9. Apply Error & Data Handling to the UI

Episode complete

Play next episode

Next
Save for later
About this episode
See versions

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 8. Build Common UI Components - Part 3 Next episode: 10. Add Actions & Handlers

The student materials have been reviewed and are updated as of September 2022.

In ui/bookReviewDetails/BookReviewDetailsActivity file, within BookRevBookReviewDetailsInformationiewItem() composable function, replace CoilImage() composable by AsyncImage() composable with updated parameters. CoilImage composable is old and not compatible with current Jetpack Compose version.

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

You can unlock the rest of this video course, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.

Demo

To make sure your forms don’t let the user store empty data, you need a way to disable actions or show errors, when the data is invalid. To do that, you need to apply error and data handling!

InputField(
  value = bookNameState.value,
        ...
  isInputValid = bookNameState.value.isNotEmpty()
)

InputField(
  value = bookDescriptionState.value,
        ...
  isInputValid = bookDescriptionState.value.isNotEmpty()
)

ActionButton(
  ...
  isEnabled = bookNameState.value.isNotEmpty()
      && bookDescriptionState.value.isNotEmpty()
      && _addBookState.value.genreId.isNotEmpty()
)
isInputValid = bookUrl.value.isNotEmpty()

...

isInputValid = bookNotes.value.isNotEmpty()

...

val pickedBook = _bookReviewState.value?.bookAndGenre

isEnabled = bookNotes.value.isNotEmpty() && bookUrl.value.isNotEmpty()
      && pickedBook != null && pickedBook != EMPTY_BOOK_AND_GENRE

private val _bookReviewDetailsState = mutableStateOf(EMPTY_BOOK_REVIEW)
private val _genreState = mutableStateOf(EMPTY_GENRE)
val bookReview = _bookReviewDetailsState.value
val genre = _genreState.value
Column(
  modifier = Modifier
    .fillMaxSize()
    .scrollable(rememberScrollState(), orientation = Orientation.Vertical),
  horizontalAlignment = Alignment.CenterHorizontally,
) {

  Spacer(modifier = Modifier.height(16.dp))
Card(
  modifier = Modifier
    .size(width = 200.dp, height = 300.dp),
  shape = RoundedCornerShape(16.dp),
  elevation = 16.dp
) {
  CoilImage(
    data = bookReview.review.imageUrl,
    contentScale = ContentScale.FillWidth,
    contentDescription = null
  )
}

Spacer(modifier = Modifier.height(16.dp))

Text(
  text = bookReview.book.name,
  fontWeight = FontWeight.Bold,
  fontSize = 18.sp
)

Spacer(modifier = Modifier.height(6.dp))

Text(
  text = genre.name,
  fontSize = 12.sp
)
      Spacer(modifier = Modifier.height(6.dp))

      RatingBar(
        modifier = Modifier.align(CenterHorizontally),
        range = 1..5,
        isSelectable = false,
        isLargeRating = false,
        currentRating = bookReview.review.rating
      )

      Spacer(modifier = Modifier.height(6.dp))

      Text(
        text = stringResource(
          id = R.string.last_updated_date,
          formatDateToText(bookReview.review.lastUpdatedDate)
        ),
        fontSize = 12.sp
      )

      Spacer(modifier = Modifier.height(8.dp))
      Spacer(
        modifier = Modifier
          .fillMaxWidth(0.9f)
          .height(1.dp)
          .background(
            brush = SolidColor(value = Color.LightGray),
            shape = RectangleShape
          )
      )

      Text(
        modifier = Modifier.padding(start = 20.dp, end = 20.dp, top = 8.dp, bottom = 8.dp),
        text = bookReview.review.notes,
        fontSize = 12.sp,
        fontStyle = FontStyle.Italic
      )

      Spacer(
        modifier = Modifier
          .fillMaxWidth(0.9f)
          .height(1.dp)
          .background(
            brush = SolidColor(value = Color.LightGray),
            shape = RectangleShape
          )
      )