Newsletter Issue #140

Published: 2022-11-08

This week, we look at single-select lists and tables. We learn about Relay, shaders, and intrinsics. We also mock composables, which does not seem like a friendly thing to do, but I may be reading too much into the terminology. 😉

And I explain how this newsletter is probably on the move.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

How Can I Implement Single-Select in a LazyColumn()?

Imagine a LazyColumn() of radio buttons — the desired UX is to have just one of those radio buttons selected at any point in time. Implementing something like this in Compose UI is not hard, but you do need to model it correctly: whether a given row is selected is a property of the row, not the list. See how this works in this week’s highlighted Stack Overflow question.

How Can I Render a Table?

A table is a grid where column sizes are determined based on the width of the largest cell in the column. Implementing this is not nearly as bad as I would have thought, courtesy of Compose UI’s concept of intrinsics. Learn more in this week’s highlighted Kotlinlang #compose Slack thread.

Composable Commentary

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

Video: Building apps with Relay, Figma, and Jetpack Compose

Liam Spradlin and Louise Macfadyen of the Material Design team walk us through Relay, Google’s new plugins for Figma and Android Studio that let you convert Figma components into composables.

Video: Fireside Chat on Jetpack Compose

Google’s Nick Butcher and Florina Muntenescu held a live Q&A for GDG Lviv’s DevFest.

Video: How to create shaders on Android with Romain Guy

The Coding with the Italians team invited Google’s Romain Guy to their livestream, to look at applying shaders to your composables, via the graphicsLayer() modifier and an AGSL-defined shader.

Exploring Lazy Staggered Grids in Jetpack Compose

Joe Birch is back, looking at LazyVerticalStaggeredGrid(), LazyHorizontalStaggeredGrid(), and StaggeredGridCells() for implementing lazy staggered grids. Joe explores customizing the number of columns based upon screen width, adding spacing to grid items, and more!

Medium: A focused TextField will wrongly intercept OnBackPress event in Jetpack Compose

Julien Bouffard points out another spot where Compose UI still has some bugs. Back navigation has some problems when a TextField() has the focus, where it takes three back nav events rather than two to trigger a BackHandler. Julien provides a workaround via your own onKeyEvent() modifier.

Marquee with Jetpack Compose

Victor Brandalise needed a marquee effect: text that animates within a shorter width than the text ordinarily would take up. Surprisingly, Victor did not find an out-of-the-box solution for this, necessitating development of a MarqueeText() composable to fill the gap.

Medium: ConstraintLayout In Jetpack Compose

Samir Shaikh examines ConstraintLayout() and how it can be used to replace nested Row() and Column() composables. Samir also looks at how to use other classic ConstraintLayout features, like guidelines and barriers, with the ConstraintLayout() composable.

Compose by example: Intrinsics

James Shvarts looks at IntrinsicSize.Max and IntrinsicSize.Min and how you can apply them to width() and height() modifiers to have the size react to the sizes of child composables (e.g., the minimum or maximum height of elements in a Row()).

Medium: Implement Integration Tests in Jetpack Compose Android Apps

Siva Ganesh Kantamani explores writing UI tests that run on a device or emulator, specifically to test navigation from screen to screen.

Resource Roundup

100% pure code!

GitHub: jeppeman / mockposable

Jesper Åman created extensions for MockK and Mockito-Kotlin that support composables. Mostly, this is for unit tests of composables outside of Compose UI, such as testing some Molecule composables.

GitHub: supabase-community / supabase-kt

If you use Supabase as a Firebase replacement, you may be interested in this Kotlin/Multiplatform library that supports Supabase access from Compose, Compose for Desktop, and Compose for Web.

GitHub: Jaseemakhtar / ComposeShimmer

Jaseemakhtar brings us a shimmer() modifier to easily add a placeholder shimmer to composables.

…And One More Thing

When I started this newsletter, nearly three years ago, I settled on Revue to handle registration and distributing the emails. At the time, they were an independent startup and had a reasonable UI and mail delivery system. However, I soon elected to keep my own archives, rather than use theirs. Partly, that is because I did not like their archival system. But I also wanted more control, in case I had to move to another newsletter service. After all, independent startups often do not remain that way. Besides, static content like newsletter archives is fairly easy to set up (FWIW, I use Jekyll).

Last year, Revue was bought by Twitter. At the time, my reaction was “this won’t end well”. However, I did not have a concrete reason to make any changes, so I stuck with them.

Now, Revue is rumored to be on the chopping block.

Even if Revue survives the rest of 2022, though, I have little faith that it will stick around for a reasonable length of time. As you may have noticed, Twitter is going through some upheaval right now. Whether you think that upheaval is great or a disaster, it is upheaval, and that does not benefit me (or Twitter’s advertisers) in the slightest. Moreover, it feels like that upheaval is likely to endure for a while.

So, I will be moving the registration and email distribution elsewhere. I am piloting Buttondown, as it seems tailor-made for what I could really use: Markdown-based newsletters with optional archiving. I considered Ghost, since it is open source and backed by a non-profit, but it felt like overkill.

For those of you who receive this newsletter via Revue emails, I will aim to keep you posted on the transition. And, if you have any questions or concerns, you can always reach out.