jetc.dev Newsletter Issue #95

Published: 2021-12-14

This week, we look at detecting touch events in a composable and removing jank from an animation. We poke at slot tables and the slot-based API, and we learn more about semantics. We visit another Navigation for Compose replacement library and a gist to turn us all into blockheads. And I ponder converting XML drawable resources into composables.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

How Do We Detect Touch Events Inside a Composable?

Many composables support the clickable() modifier to detect simple click events. However, what if you have a larger area and need to know the coordinates of touch events within there? The pointerInput() modifier and detectTapGestures() are here to help, as we see in this week’s highlighted Stack Overflow question.

How Do We Identify the Source of AnimatedContent Jank?

As we have seen a lot in this newsletter, excess recompositions is a major source of jank and general poor performance. See how a very slight tweak is a composable can dramatically improve the performance of an animation, in this week’s highlighted Kotlinlang #compose Slack thread!

Composable Commentary

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

Video: Jake Wharton and Leland Richardson Answer Your Questions About Compose

The “Code with the Italians” team invited Google’s Leland Richardson and Square's Block’s Jake Wharton to discuss Compose and its internals, such as how the slot table system works.

Slotting In with Compose UI

Chris Banes provides an overview of the rationale and use of Compose’s slot-based API, where a composable takes other composables as parameters. The objective is to reduce the responsibility of any individual composable, delegating other responsibility to the supplied composables.

Videos: The Rest of droidcon London 2021

A couple of weeks ago I mentioned a pair of droidcon London 2021 presentations on Compose UI. At the time, the droidcon site was misbehaving, and I could not see the other presentations. That has since been fixed, and there were three other presentations on Compose UI:

Medium: Jetpack Compose — Optimize List Performance with Key

Pankaj Raj points out that using the right key in your LazyColumn() or LazyRow() can make a lot of difference in the performance, particularly for mutable lists where items might stay the same but change position within the list. Keys allow Compose to detect those moves and avoid unnecessarily re-creating composables.

Video: Jetpack Compose: What’s The Fuss?

Omolara Adejuwon delivered a presentation at the DevFest Inspire event, reviewing the basics of Compose UI and what value it delivers to Android developers.

Slides: Semantics in Jetpack Compose

Bryan Herbst delivered a presentation on the role of semantics in Compose UI, both for accessibility and for testing. Bryan published the slides, reviewing the use of Modifier.semantics() and how those semantics get mapped into AccessibilityNodeInfo objects for use by TalkBack and similar accessibility services.

Medium: Jetpack Compose Enables JSON Defined View Layout

Elye returns, examining the basics of server-defined UI, where a Web service not only provides data but information about how to render that data.

Resource Roundup

100% pure code!

GitHub: mobnetic / compose-advanced-preview

The team from Mobnetic created an AdvancedPreview() composable, designed to wrap a function for use with @Preview. AdvancedPreview() gives you more options for rendering the preview, and more importantly makes the resulting image available outside of the IDE preview pane (e.g., as screenshots for documentation).

GitHub: alphicc / Brick

Petr Shubin created another replacement for Navigation for Compose, with a wide array of features, including deeplink and arguments support, support for multiple modules, support for sheets/tabs/dialogs, and more.

Gist: zach-klippenstein / Blockify.kt

Google’s Zach Klippenstein created a set of composables that combine to wrap some composable (say, an Image()) around a cube (like, say, the avatars for certain members of Block).

GitHub: copper-leaf / thistle

GitHub user Copper Leaf created a library for processing strings with inline markup. The library then provides converters from that single markup syntax to Spannable (for classic Views), AnnotatedString (for Compose UI), and ANSI codes (for terminal use).

…And One More Thing

I will be tossing out ideas for tools and libraries from time to time here — this is one of those.

For a lot of developers, the “magic” tool would be something that could convert a layout resource into composables. There have been some experiments to that effect. However, that is a massive undertaking, even if we limit ourselves to framework and Jetpack widgets. The sheer volume of view properties alone is daunting, let alone working out how to map, say, the rules of TableLayout into composables. It is doable, but it is a lot of work. If you start adding in data binding and arbitrary third-party views, and it gets even worse.

However, there seems to be a reasonable chunk of “low-hanging fruit” in the resource space that could be migrated to composables more easily. One would be XML-defined drawable resources.

Most of the XML drawables implement fairly simple rules:

  • LayerListDrawable stacks N other drawables on the Z axis

  • LevelListDrawable chooses a drawable from a list of candidates based on a supplied “level”

  • ClipDrawable clips a drawable, RotateDrawable rotates a drawable, etc.

  • And so on

VectorDrawable is complex, but given that we have SVG-to-composable tools, there is a decent chance that creating a composable from a VectorDrawable is not that hard.

Are these “life altering” sorts of tools? No. But, for developers looking to move to a pure Compose UI setup, these tools could be useful options. They would be of particular interest to developers looking to use Compose outside of Android (e.g., Compose for Desktop), since Android resources are only useful for Android.