jetc.dev Newsletter Issue #106
Published: 2022-03-08
I’m back! 👋
This week, we peek at 1.1.1
and 1.2.0-alpha04
. We look at design systems
and accessibility. We explore rich text, including a native Compose rich text editor.
And we spend time looking at every Compose developer’s favorite subject: state management.
And I grumble about Compose magic and developer documentation again.
Release Roundup and Alpha Analysis
Reviewing the release notes for the latest Jetpack Compose update!
Back before the one-week hiatus for this newsletter, Google released Compose 1.1.1
.
This appears to be simply some bug fixes, as one would expect from a patch release.
We also got 1.2.0-alpha04
artifacts. Of note:
-
We now get lazy font loading as an option
-
LazyVerticalGrid()
has areverseLayout
parameter -
Compose Material now exposes
TextFieldDecorationBox
andOutlinedTextFieldDecorationBox
, designed to be used withBasicTextField()
to give us a Material-ish look while offering more flexibility in terms of the details
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Can We Save a Composable Lambda?
It is tempting to try to shove all sorts of things into rememberSaveable()
,
including things that cannot be saved to disk… such as a lambda expression.
See where this approach goes wrong in this week’s highlighted Stack Overflow
question.
Why Are Stateful APIs Discouraged?
The official position is that an API should not expose State
or MutableState
,
but rather a property that might be backed by State
(e.g., var foo by mutableStateOf(bar)
).
Learn why that is the case in this week’s highlighted Kotlinlang #compose
Slack
thread!
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Video: Custom Design Systems in Compose
Google’s Nick Rout delivered a presentation for GDG Cape Town, exploring the range
of theme customization, from simply tweaking MaterialTheme()
to creating a completely
customized design system.
Video: Jetpack Compose Intro and Beyond
Maia Grotepass and Thomas KĂĽnneth collaborated on a set of presentations for the Developer User Group. Maia delivered a live coding session demonstrating the basics of Compose UI, and Thomas explored Compose 1.1 and what it provides to developers and explored Material3. The session wrapped with a panel discussion.
Compose remember vs remember mutableStateOf
It is easy to remember()
, but sometimes we fail to remember the mutableStateOf()
…
yet things still seem to work. James Shvarts walks us through the different pieces
of remember()
and mutableStateOf()
and explains when to use the combination
and when to simply remember()
.
Jetpack Compose Accessibility: Getting Started
Victoria Gonda explains the importance of accessibility and walks us through a tutorial that adds accessibility features to a Compose UI app. This includes how to set up a test device with accessibility services like TalkBack enabled and how to use them for testing your work.
Building an Authentication Form using Jetpack Compose
Joe Birch is back, with the first of a two-post series on building a login/signup screen using Compose UI. This post walks through setting up models for the different aspects of the login/signup flow and assembling the screen, including professional touches like IME action button support, password toggles, and more.
Complete guide to Rich Text in Jetpack Compose
Dmytro Shuba explores how we can apply formatting to text in Compose Material, looking
at styling Text()
and using AnnotatedString
for defining styles for individual segments
of text.
Medium: How to Show Snackbars Across Multiple Screens in Jetpack Compose
A problem in classic activity/fragment development is maintaining certain UI
elements across screen transitions, such as keeping a snackbar visible while the
user navigates. Varsanyi Botond explores how to accomplish this in Compose UI,
using a central Scaffold()
shared by the various screens.
Flying Hearts Animation in Jetpack Compose: Quick and Easy Edition
Aida Issayeva returns, this time showing an implementation of Instagram’s
“flying hearts” animation in Compose UI. Aida uses a Canvas()
to render the heart,
plus visibility and position animations for the flying effect.
Other Interesting Links
- Into the Compose-Verse: A Beginners Guide To Jetpack Compose: State Management
- Jetpack Compose UI testing
- Medium: What do you need to know before upgrading to Android Compose 1.1.0
- Medium: iOS Like Modal View Dialog Animation In Jetpack Compose
- Medium: Cleaner Previews in Compose with PreviewParameter
- Medium: Responsive Layout Grid using Compose
- Video: Building StateFlows with Jetpack Compose
- Medium: Bottom Navigation with Jetpack Compose
- Medium: Sharing ViewModel within Jetpack Compose Navigation using Hilt
- Medium: Jetpack Compose: Implement Perlin Noise Animation Interpolator
Resource Roundup
100% pure code!
GitHub: pChochura / Compose-Rich-Text-Editor
Paweł Chochura created a RichTextEditor()
composable, supporting character
formatting (bold, italics, etc.), line alignment (left, center, right), plus
text size and color.
GitHub: EhsanMsz / MszProgressIndicator
GitHub user EhsanMsz brings us a library of 28 different progress indicator composables: circles, squares, lines, triangles, and… a certain video game character.
GitHub: re-ovo / slanted-text-compose
A popular UI pattern is the diagonal banner, sometimes used as a badge on some other
UI element. GitHub user re-ovo created a SlantedText()
composable for implementing
such an element in Compose UI.
GitHub: dokar3 / ExpandableText
Another popular UI pattern is to have a piece of text that initially shows a few lines
and offers some clickable element to let the user expand to see the full text.
GitHub user dokar3 put together an ExpandableText()
composable for implementing this
pattern.
Other Interesting Links
- GitHub: DmytroShuba / DailyTags (Markdown renderer)
- GitHub: loukwn / StageStepBar (discrete progress bar)
- GitHub: p-lr / MapCompose (tiled map renderer)
- GitHub: bonnjalal / Scale-OverlayView (overlay grid for sizing/cropping)
- GitHub: theapache64 / twyper (Tinder-style swiping UI)
- GitHub: popovanton0/heart-switch (heart-shaped toggle widget)
- GitHub: adrianwitaszak / neumorph-ui (neumorphic widget set)
…And One More Thing
This week’s One Off the Slack hearkens back to one of my original concerns with Jetpack Compose: sometimes, it is “too cute by half”.
In that Slack thread, Google’s Adam Powell rejects the notion that developers should
worry about whether a particular API is backed by some form of State
or something
else that can trigger recomposition. He stated:
I do think it’s valid for public API types… to call out in their documentation if their properties are snapshot-observable, but with compose it’s more of a baseline assumption.
The Compose snapshot system, as a form of software transactional memory, is a seriously
cool concept, but it contributes to the “Compose is magic” vibe. That is exacerbated
by the fact that there is no documentation from Google about the Compose snapshot
system, apart from very limited class documentation. For example,
"snapshot invalidation"
has zero hits right now in the developer documentation,
yet Adam focuses on that phrase a lot in the Slack thread.
Zach Klippenstein wrote a seminal set of blog posts
covering state and diving deep into the snapshot system.
Google integrating something like those posts into developer.android.com
would be a significant help. Without that, “snapshot invalidation” and similar terms
are going to be expert-level topics at best.
IOW, so long as “snapshot invalidation” remains magical, most developers are going to largely ignore it
to the greatest extent possible.
Right now, we are already fairly deep into rules like “if your composable is not recomposing,
you probably forgot remember { mutableStateOf() }
”. While technically that is incorrect —
there are other options beyond MutableState
— busy coders are not going to care.
They are going to reach for the tool in the toolbox that they know solves the problem, because
recomposition is ancillary to the real problem that the developer is trying to solve.
My hope is that someday there will be adequate official documentation for the snapshot system, and that “snapshot invalidation” will appear in the docs.
Or, you can subscribe to the Atom feed or follow Mark Murphy in the Fediverse.
Recent Issues:
- 2024-10-01: Lazy grids! Focus! @colinmarsch@androiddev.social on CMP accessibility! @skydoves@androiddev.social on Landscapist! @sinasamaki@androiddev.social on Slider()! And... what is it?!?
- 2024-09-24: A Compose security fix and a new alpha! clipToBounds()! Localization! offset()! @skydoves@androiddev.social on server-defined UI! Bottom sheets! And... someone set us up *3* BOMs?!?
- 2024-09-17: Compose 1.7.1 and Compose Multiplatform 1.7.0-beta02! Flow layouts! TV Compose! SharedBounds! Image cropping! And... why does remember() not seem always to remember?!?