jetc.dev Newsletter Issue #55

Published: 2021-03-09

This week, as we gear up for a possible beta02 release, we look at scrolling lists: how to disable the scrolling and how to have stateful rows. We also hear from Google’s Leland Richardson, spend time with architecture, spend even more time with clocks, and peek at a reusable pull-to-refresh composable. Plus, I beg you to start thinking about what else you can fix in your UI as you migrate to Compose… such as thinking about other form factors.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

How to Disable and Enable Scrolling?

LazyColumn() and LazyRow() offer built-in scrolling. However, you might have the desire to temporarily disable scrolling, then re-enable it later. This is not offered by those composables, but Google’s Ryan Mentley shows us how we can implement it ourselves, in this week’s highlighted Stack Overflow question.

Stateful Rows in a LazyColumn()

The good news: having rows with state (e.g., a checkbox) is a lot simpler with Compose UI than it is with RecyclerView. The bad news: you still need to think through the state management, as we see in this week’s highlighted Kotlinlang #compose Slack thread.

Composable Commentary

Posts, videos, and other new information related to Jetpack Compose!

Video: Jetpack Compose Beta AMA

Google’s Leland Richardson hosted an hour-long livestream where he took questions about Compose and Compose UI from the audience and offered up his best answers!

How To Understand Composables & Recomposition

Ryan Kay walks us through the act of recomposition, including when it occurs and what all gets recomposed. If you prefer a video format, Ryan has a short YouTube video on the same subject. He also wrote a post this week on modeling UI events with sealed classes in Compose.

Architecture in Jetpack Compose — MVP, MVVM, & MVI

Ian Alexander looks at how the MV* architecture patterns that we all know and hate love translate into the world of Compose and Compose UI.

Getting ready for Declarative UIs — Part 2 — Implementing Unidirectional Data Flow

Raul Hernandez Lopez gives us another peek at architecture in Compose and similar sorts of reactive/declarative UIs. This time, Raul explores the meaning and implementation of a “unidirectional data flow”, which is a popular structure that Compose supports well.

Compose O’Clock

This week is all about Compose keeping track of time, courtesy of the countdown timer called for in the second week of the Android Developer Challenge. However, there are other types of clocks. Márton Braun and Aurimas Liutikas each demonstrated creating an animated clock using Compose UI, using vertical strips of numbers for each digit in the time, sliding up and down as the time changes.

Compose (UI) beyond the UI (Part III): No AAC-ViewModel and a sample app

Jordi Saumell continues a walkthrough of Compose UI, looking at how we can avoid the Jetpack ViewModel entirely. This time, Jordi walks through… yet another clock app, showing how the time gets updated without needing a ViewModel to emit changes to that time.

Video: Step It Up: Compose for Desktop

Nishant Srivastava delivered a short presentation on Compose for Desktop at FOSDEM 2021, looking at how it works and showing how to get started with desktop app development.

Mavericks, Meet Jetpack Compose

Mavericks (or MvRx) is an RxJava-powered MVI app framework published by AirBnb. Gabriel Peal announced mavericks-compose, which provides Compose integration for Mavericks.

Wrap Compose IDEA/Android Studio Plugin

Rasul Aghakishiyev has published a small IDE plugin that wraps a selected composable in one of a number of common composables, such as Box() or Row().

Fix: Jetpack Compose observeAsState Type Error has no method

Paul Blundell reminds us that you need to add import androidx.compose.runtime.getValue and import androidx.compose.runtime.setValue to avoid delegate problems when using observeAsState() to recompose based on changes in the value of a LiveData.

Resource Roundup

100% pure code!

GitHub: poculeka / PullToRefresh

Adrian Pucułek put together a small library containing a pull-to-refresh composable. You can wrap a LazyColumn() in a PullToRefresh(), where you supply an onRefresh parameter to get control when the gesture is triggered so you can update your data model and recompose your UI.

GitHub: jeziellago / compose-markdown

Jeziel Lago brings us a library that offers a MarkdownText() composable that handles rendering Markdown-formatted text.

GitHub: STAR-ZERO / ComposeFlowLayout

A “flow layout” continues to be popular: show as many children as possible on the current row, then start a new row and continue. We saw one implementation of this back in Issue #32. Kenji Abe offers up another library with a FlowLayout() composable, where you provide the spacing of items, plus the items itself, and FlowLayout() flows them across however many rows are required.

Gist: vitorprado / RatingBar.kt

Vitor Prado brings us a small RatingBar() composable, where we provide the rating as a Float in the 0-5 range and it renders a row of stars for that rating, including a partial final star.

…And One More Thing

Now that Compose and Compose UI are in their first beta, teams may start to think about beginning to use these technologies in their apps. If your team is among them, you should consider taking this opportunity to also clean up other shaky practices in your current UI implementation.

For example, you might want to stop thinking of screen sizes.

Some Android developers are fixated on finding screen dimensions, then trying to use them. For example, in Compose UI, you can find the screen height using LocalConfiguration.current.screenHeightDp.

However, this is not really a good idea… because your app may not be using the full screen.

Most Android devices nowadays support split-screen mode. Many users will not be using that mode, but some will. In split-screen mode, your app’s window is not going to take up the full screen, but rather only part of it.

Chrome OS devices, and specialty “desktop-style environments” like Samsung DeX, use Android’s free-form multiwindow support. In this case, your app’s window also is not going to take up the full screen, but rather only part of it. Many users will not be using this sort of device or environment, but some will.

With “foldables”, the screen size can change, and users may be more prone to use split-screen mode. We might soon get “rollable” phones. Who knows what other form factors will follow those? After all, who would have predicted the LG Wing?

(personally, I half expect the next segment to be “crumple-ables”)

You might look at all of those and conclude that none of them are very popular. That may well be true. However, combined, the number of users using one of those environments might be interesting.

More importantly, manufacturers keep trying, presumably with some encouragement and support from Google. Eventually, something is going to become a hit, either on its own merits or because Apple decides that it is cool.

In other words, the era of “one screen = one app” most likely is coming to a close.

So, rather than think in terms of “how big is the screen?”, think instead in terms of “how much space do I have?”. We saw this a few weeks ago in the “How Big Are We?” post in the “One Off the Slack” series. You can use things like BoxWithConstraints or onSizeChanged() to be able to adapt your UI to match the available space, and let the system worry how much space that is.

Adopting Compose UI will require a significant overhaul of your UI code, as you adopt Compose UI progressively through your app. While you are making those changes, think through what other assumptions your code is making, and see if you can avoid making those assumptions, to better future-proof your UI. After all, you never know when someday your app needs to run on a phone that the user can just crumple up and shove in their pocket.