jetc.dev Newsletter Issue #76
1.0.0 stable is here! 🎉
Let me be the 39,304’th person to congratulate the entire Compose team for all their hard work on getting the inaugural edition of Compose out!
However, it looks like the first 1.1.0 alpha is coming soon, so apparently the team does not get to rest. And, neither do newsletter authors!
This week, we see what Twitter is doing with Compose, and we take a couple of peeks at text rendering options. A pair of library authors explain why they did what they did. We play around with bottom sheets, and I pass along Rebecca Franks’ warning that Compose may not behave quite the same on all Android OS versions.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Sometimes, we want to have the peek height of a
be based on the size of the content that the bottom sheet will show. Using
onGloballyPositioned() modifier is one approach for handling this,
as we see in this week’s highlighted Stack Overflow question.
A fairly common pattern in an Android app is to have a few screens be available
generally, but have the rest require authentication. And, if that authentication
times out after a while, you might find yourself needing to re-route the user to
a login UI from an arbitrary spot in the app. Figuring out how to do this with
as little code duplication as possible is the subject of this week’s highlighted
#compose Slack thread.
Posts, videos, and other new information related to Jetpack Compose!
Nacho López delivered a presentation at the 360AnDev 2021 conference, looking at the adoption of Compose UI at Twitter and how it related to a previous framework they created (Weaver), with a particular emphasis on architecture patterns.
If you are new to Compose, first, 👋. Then, you might want to read this post from Pamela Hill, outlining some of the key concepts and phrases that you will run into as you start trying to absorb Compose.
Continuing on the theme of text, Shreyas Patil explores the
AnnotatedString.Builder, showing how you can blend arbitrary composables
into your rendered text, rather than dividing the text and placing pieces around
Jaewoong Eum is back! Jaewoong is the creator of the Landscapist image-loading library. In this post, Jaewoong explains the reasons for creating the library and how to use it for getting network-supplied images into your composables, including applying animated effects like shimmers and reveals.
Similarly, Peter Laurence created the MapCompose library for rendering a tile-based map, with panning and pinch-to-zoom. Peter’s post explains where this library came from and how to integrate it into your app, including supplying tile sources, placing pins and paths, and more!
Ilker Aslan ran into a problem with
BottomSheetScaffold(): the bottom sheet that
it displays is not modal, blocking input to the rest of the UI. In this post, Ilker
explains the process required to find a way to set up a modal
borrowing bits of internal Compose UI code to pull off the desired effect.
Other Interesting Links
- Fun with Compose: Bad UI in a Great Framework
- SwiftUI vs. Jetpack Compose: Why Android Wins Hands Down
- Video: Introduction to the Future of Android UI Development
- Opening a PDF in a Jetpack Compose Application
- Designing a Bottom Navigation Bar with Jetpack Compose
- Medium: Unboxing Jetpack Compose: Experience My First Compose App
100% pure code!
Halil Ozercan has taken over the
compose-richtext family of libraries from Zach Klippenstein.
As you can see in the main documentation site,
the libraries include everything from Markdown parsing and printing to a
PowerPoint-style slideshow composable.
…And One More Thing
One of the touted claims of Jetpack Compose is that it is “unbundled”. This means
that it comes in the form of versioned libraries that we add to our apps. This is
in contrast to most of the widgets in the classic
View system, which are framework
classes and are part of the firmware. Framework classes are necessary, but we do not
control them. In particular, we cannot upgrade them, so there may be variations
in behavior between OS versions. And manufacturers can mess with them, so there may be
variations in behavior between device models.
Being unbundled means that we control what versions of Compose that we use and that we can upgrade on our own timetable.
But, as Rebecca Franks pointed out in a Twitter thread last year,
there are limits. In the end, everything winds up hitting some sort of framework
class. And for Compose UI, the key one is
Canvas is Android’s 2D drawing API. It is backed by Skia.
Canvas and Skia do change over time.
This means that you may still run into hiccups, where the same composable renders
differently on different devices. I would expect fewer manufacturer-specific
hacks here, but older devices may have
Canvas bugs that were fixed in later versions.
Canvas and Skia simply change, and those changes can have impacts on whatever
uses them, such as Compose UI. Rebecca’s thread has some examples of distinctly
different rendering behavior based on API level.
With luck, for stock composables, a lot of these variations have been addressed,
so we get consistent behavior. However, whenever you rely on luck, there is a chance
that your luck will run out. Things get worse if you are using the
composable directly, which will be a reasonably popular approach for creating
“from scratch” custom composables.
While overall we should get a more consistent UI with Compose across devices and versions, that is not a guarantee, and testing will still be needed.
(hat tip to Seb Roggi for retweeting Rebecca’s thread)
- 2023-11-21: Compose/Material3/Wear Compose updates! remember()! Adaptive layouts! Compose Multiplatform in 2024! @email@example.com on BasicTextField2()! Compose Multiplatform charts! And... is TV Compose in trouble?!?
- 2023-11-14: Compose Compiler! BasicTextField2()! @firstname.lastname@example.org and animations! Optimization! @email@example.com, JetBrains, and Fleet! JetBrains and plotting! And... we collapse?!?
- 2023-11-07: Compose Multiplatform! Chips in fields! Diffing! Custom fonts in Glance app widgets! Heatmaps! PIN input! And @firstname.lastname@example.org is in a bit of a haze?!?