Newsletter Issue #45

Published: 2020-12-22

alpha09 is out, wrapping up the 2020 Compose releases! In this week’s issue, we look at some of the alpha09 changes. We also peek at how Compose impacts our APK size and complexity, along with how to implement a staggered grid. We see what a custom design system looks like, and I take a look at a Scaffold() mistake that I made.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

Adding an Overflow Menu

We have lots of UI patterns with classic views that we will need to replicate in Compose UI. One is the overflow menu in an app bar, for lower-priority items. With ActionBar and Toolbar, we would use things like app:showAsAction="never" in menu XML resources. With Compose UI, instead, we create our own DropdownMenu(), as we see in this week’s highlighted Stack Overflow question.

How Default is a Default?

Default values for things like padding are not a Compose thing — those decisions are part of a design system, such as Compose Material. That has an impact on the API that we wind up using, as we see in this week’s highlighted Kotlinlang Slack thread.

Composable Commentary

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

Compose Runtime Alpha 09 Release Notes

If you were using SlotTable, SlotReader, and SlotWriter, they are no longer part of the public API. Also, if you had been annotating properties with @Composable, you will need to switch to annotating their getters with @Composable instead.

Compose Foundation Alpha 09 Release Notes

They changed names again: LazyColumnFor() and LazyRowFor() are deprecated, replaced by LazyColumn() and LazyRow(). However, they added a bunch of other features for these, including reverseLayout and custom arrangements. They extracted a Scrollable interface and added LazyVerticalGrid().

Compose UI Alpha 09 Release Notes

There were quite a few changes (each small) this time — you should consider reading the full release notes. In particular, if you have been working with keyboard input, autofill, accessibility, or dialogs, you will want to peek at what has changed.

Compose Material Alpha 09 Release Notes

The biggest news, for those creating their own design systems, is that the ripple effect for clicks has now been extracted into an androidx.compose.material:material-ripple library, so you can use those ripples without needing the rest of Material. Also, watch out for a bunch of renames related to ...Constants classes, as they are now ...Defaults classes, with changes in their property names to match.

Jetpack Compose — Before and After

Google’s Chris Banes rewrote his Tivi sample app using Compose UI. In this official Medium post, he compares the two implementations, not from a coding standpoint, but in terms of how big the resulting app is, in terms of APK size, build time, method counts, etc.

Using Jetpack Compose Scaffold as Template

Elye continues to be on a roll! Here, he reviews the Scaffold() composable and how to use it to set up the skeleton of a typical Android screen.

StaggeredVerticalGrid of Android Jetpack Compose

Elye’s second post looks at implementing a staggered vertical grid — columns where the items in each column can vary in height — using Compose UI. Specifically, he demonstrates how to use Layout() to place child composables at specific locations within a parent — in this case, controlling the number of columns and taking into account the height of each element in a column.

Video: Compose Your Next App

droidcon APAC 2020 released the videos for their recent virtual developer conference! Three were focused on Compose and Compose UI. This one, by Himanshu Singh and Niharika Arora, focuses on the basics of using Compose UI.

Video: Explore the future of Android UI with Jetpack Compose

Our second droidcon APAC 2020 video, from Gurupreet Singh, is another introduction to Compose UI.

Video: Jetpack Compose for Games & Animations

The third droidcon APAC 2020 video, from Wajahat Karim, takes another look at using Compose’s Canvas() and animation capabilities, with an eye towards basic game development.

Resource Roundup

100% pure code!

GitHub: sigmadeltasoftware / CalPose

Bojan Belic brings us a library for a calendar composable, to fill a role reminiscent of CalendarView in the classic View system.

…And One More Thing

Everybody makes mistakes.

No programmer get very far in programming without having some sort of mistake, caught at compile-time or runtime. This is “part and parcel” of software development.

Newcomers to programming, or to a particular system, are more likely to make mistakes, owing to their relative inexperience. Moreover, newcomers are likely to make predictable mistakes. We see this all the time in classic Android development:

  • Developers who try calling methods from Activity from a field or property initializer, before onCreate() gets called, and fail because many of those inherited methods are not ready yet

  • Developers who try referencing a widget field or property before calling findViewById() to populate that field or property, or calling findViewById() before calling setContentView() (in an activity)

  • Developers who try working with files using bare filenames, as you can in desktop Java, rather than with fully-qualified paths, as you need in Android

  • And so on

A well-written system tries to help developers get past predictable mistakes quickly.

Sometimes, that comes from designing the API to avoid the mistakes. If the API prevents you from making mistakes, you are less likely to make mistakes. If the default use of the API prevents developers from making mistakes, newcomers are less likely to make mistakes initially, as often they will stick to the defaults.

Sometimes, that sort of API design is impractical. At that point, helping developers get past predictable mistakes comes down to having actionable error messages.

For example, this past Saturday, I was merging a couple of Compose samples together, and I crashed with a "The target value must have an associated anchor" error message when trying to open a drawer attached to a Scaffold(). It turns out that I missed providing the scaffoldState parameter to Scaffold(), even though I was using the ScaffoldState elsewhere in the Scaffold() setup. This was a classic copy-paste problem, where I was copying individual parameters rather than the full Scaffold() call. However, the error message itself was completely unusable (what “target value”? what “anchor”?). I wound up comparing and contrasting a working implementation with the failing one, until I noticed the missing parameter.

As Elye points out, Scaffold() is a fine starting point for a Compose screen. We should expect newcomers to use Scaffold() a lot. As a result, the more we can do to help newcomers get their Scaffold() implemented correctly, the more quickly those newcomers will gain comfort with how Compose works. Failing to supply scaffoldState is a predictable mistake; ideally, Scaffold() fails in a way that helps newcomers understand what might have gone wrong.

As you start creating composables, for your team or for Android developers worldwide… ideally, think through how developers will make mistakes with those composables, then take steps to try to get developers past those mistakes.