jetc.dev Newsletter Issue #112
This week, we look at snapping
LazyRow() composables and whether widgets should be
stateful. We spend time on performance analysis, including the recently-added
Compose compiler metrics reports. We look at animations, both how to set them
up and how to test them. SmartToolFactory has a couple of new libraries, so we
check those out. And I continue to wonder when Compose will be on TV.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
LazyRow(), like a
LazyColumn(), allows the user to scroll to arbitrary
points. However, sometimes you may want “snapping” behavior, such as always having
an item be centered or always having an item be aligned with the start edge.
Learn about how a couple of libraries give you some options for this, in this
week’s highlighted Stack Overflow question.
By default, Compose UI widgets are stateless, with state being maintained in separate
objects from the composables that render them. But, is this the only option? Learn more
in this week’s highlighted Kotlinlang
#compose Slack thread.
Posts, videos, and other new information related to Jetpack Compose!
Google’s Manuel Vivo describes what it took to migrate Google’s
architecture samples to use Compose UI
instead of the classic
View system. They left the viewmodels alone, so their samples
LiveData instead of
Flow for the reactive data streams. The post covers
developing the plans, key steps in the implementation, and a list of problems that they
Chris Banes brings us a deep dive into the Compose compiler plugin’s new ability to output reports about the contents of your composables. Chris helps you determine how best to convert that data into actionable steps to improve the performance of your Compose UI interfaces.
Vinay Gaba is back, looking at various ways to detect overcomposing: where your
composables get recomposed more frequently than is warranted. Vinay looks at
recomposeHighlighter() modifier, the same Compose compiler metrics that Chris
Banes reviewed in the preceding newsletter item, and good old-fashioned
Phil Boyd explores the steps it takes to have some composable (such as an
animate along some pre-determined but arbitrary path. Phil looks at having
dependent animations (such as having the Y position be derived from the X position),
as well as how to rotate the moving composable based upon the path position. Warning:
this post contains trigonometry.
Francesc Vilarino Guell returns, this time examining selectors, such as the
chosen item among a row of radio-button-style toggle buttons.
Francesc wanted the selection indicator to slide from the previous selection
to the newly-selected item. This resulted in a
based on a
Layout(), to wrap up all of the animation and clipping complexity.
With all these animations, it seems like we might want to test them. Alex Zhukovich has our back, with a post exploring how to set up screenshot testing with Compose’s virtual clock and Shot to create test cases for animations.
Other Interesting Links
- Medium: Jetpack Compose with Lifecycle-Aware Composables
- Medium: Two-way data binding in Jetpack Compose
- Medium: Easy Android ListView Pagination using Jetpack Compose
- Medium: Animated Placeholder with Jetpack Compose
- Medium: Using compose destinations
- Understanding Composition and Side Effects
- Medium: Jetpack Compose: everything you need to know to get started
100% pure code!
Did I mention that SmartToolFactory has been on a roll? They have also released
ScreenshotBox() composable and corresponding
ScreenshotState. These combine
to let you capture composables as bitmaps, either on a one-time basis or periodically
(for collecting a series of bitmaps).
Pavel Shurmilov has wrapped Gabriel Souza’s svg-to-compose tool into a plugin that works with IntelliJ and Android Studio. This lets you convert one (or several!) SVG images to corresponding composables.
Detekt is a static analysis tool to help you identify quality problems with your
app (code smells, etc.). However, false positives can be a bit of a problem. To help
with this, Detekt offers suppression rules, to teach Detekt situations where problems
should be ignored. One such rule is an annotation rule, and you can use that to
teach Detekt to ignore your Compose UI
@Preview-annotated functions and not complain
about those. That technique can be useful if you use dedicated
(for code that will not be used in production), instead of putting
real composables that your users wind up seeing.
…And One More Thing
Android TV is getting some love in 2022:
Android 13 seems to have some new TV-related APIs, suggesting that Android TV might continue getting OS version updates
There are rumors of new hardware (and, yes, a “Chromecast with Google TV” is an Android TV device, because branding is hard)
However, Compose UI support for Android TV still seems to be a work in progress:
The roadmap mentions “Trackpad/D-Pad navigation” as “In Focus”, so it is not yet “Done”
There is no mention of “TV” or “leanback” in the roadmap, where “leanback” is Google’s term for TV-centric user interfaces
That unfortunately overlaps with stymied progress on
View-based Leanback libraries,
which have not seen a new alpha in five months.
It would be good to know whether Google intends on having a Compose UI equivalent of Leanback or whether Android TV developers need to put their energies towards some independent implementation of the concept. Google’s Chris Sinco indicated that discussions were taking place back in February, presumably around official Compose support for TV apps. But, other than experiments like this TV launcher app, I am not seeing a lot of community activity in this space either.
Hopefully, we will get some clarity in this area in the coming weeks. After all, Google I|O 2022 is coming soon!
- 2022-08-09: droidcon Berlin 2022! Animating text! Shimmers! Recompositions! Animations! Charts! Cameras!
- 2022-08-02: Compose 1.2.0! Wear Compose 1.0.0! Gradients and text! Foldables! Drag-and-drop! And @andersullnass on snapshot testing!
- 2022-07-26: New compiler beta! Overlapping composables! RecyclerView! movableContentOf()! JSON forms! And @anafthdev_ shows us composable picker wrappers!