jetc.dev 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, beforeonCreate()
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 callingfindViewById()
before callingsetContentView()
(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.
Or, you can subscribe to the Atom feed or follow Mark Murphy in the Fediverse.
Recent Issues:
- 2024-12-10: A Compose Multiplatform alpha! Hot reload! Presentation! Sprites! Calendars!
- 2024-12-03: Rebecca Franks on clipping and masking! Stefano Natali on graphicsLayer()! FunkyMuse on type-safe nav results! And... if we have enough maps, do we need to store our maps in a Map?!?
- 2024-11-26: Math! Shared element transitions! Custom modifiers! Macrobenchmark! Adapting to platform-specific design systems! And... why does wrapContentSize() not wrap my content size?!?