jetc.dev Newsletter Issue #92
Published: 2021-11-23
1.1.0-beta03
is out, with some new APIs!
In addition, this week we look at search bars, swipe-for-action implementations, and testing (including some Compose-related Appium improvements). We look at sliders, shimmers, and unexpected state capture. And I return to a long-standing topic of mine: support for external displays.
Beta Breakdown
Reviewing the release notes for the latest Jetpack Compose update!
1.1.0-beta03
is out! And, we got new modifiers, onPlaced()
and (for LazyListScope
) animateItemPlacement()
, to
help with drag and drop! Beyond that:
-
If you use
InjectionScope
and/orMultiModalInjectionScope
, note that some things were removed. -
LazyVerticalGrid()
now supports horizontal spans -
Some bugs were fixed in Compose Material’s
DropdownMenu()
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Why Is My AndroidView
State Captured?
Bridging between composables and the classic View
system can lead to unexpected
issues. See why the update
parameter to AndroidView
is important for coping
with state changes in this week’s highlighted Stack Overflow question!
Why Does My List Not Recompose?
mutableStateListOf()
is a great function, but it only treats the list members as
state, not what is inside each of those members. If you mutate a member, by default, nothing
will happen… unless you take some steps to make the member’s contents itself be state.
Learn how in this week’s highlighted Kotlinlang #compose
Slack thread!
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Getting Started with Jetpack Compose
Kristen Halper of Microsoft’s Surface Duo Developer Experience team offers an introduction to Compose UI, with a particular emphasis on supporting large-screen and foldable devices.
Configuring SearchView in Jetpack Compose
MK writes about how to implement a search bar in Compose UI. MK’s solution uses
an OutlinedTextField()
for the search field, along with focusRequester()
,
in a TopAppBar()
.
Medium: Swipe-for-action cards like Gmail using Jetpack Compose
A UI pattern, popular on iOS, is to have list rows that swipe horizontally to expose
some actions. Harsh Mahajan demonstrates how to implement this in Compose UI,
through a library that Harsh wrote that has a SwipeableActionCard()
composable.
Medium: Automating Android Jetpack Compose using Appium
Many Android UI testers like using Appium, but most of the material on Appium is focused
mostly on the classic View
system. Raj Varma examines what it takes to get Appium
to test composables, using Compose UI’s supplied test artifacts and some new Appium
capabilities that Raj contributed.
Testing Jetpack Compose without emulator or device
Continuing on the theme of testing, Piotr Chmielowski walks us through using
Robolectric and createComposeRule()
to run some Compose UI tests as unit
tests instead of instrumented tests.
Translating Text in Jetpack Compose
Eric Martori looks at translating strings in a Compose UI application… but not by using string resources. String resources are baked into the app, which is handy but means that adding language support (or fixing translation bugs) requires shipping a new version of the app. Eric explores using a Web service as the primary source of translations, with string resources serving as a fallback.
Other Interesting Links
- Using Jetpack Compose in Production Code: First Impressions
- Video: Imperative vs. Declarative UI Development
- Video: Animated Shimmer Effect with Jetpack Compose
- Video: OCR Using MLKit and Jetpack Compose
- Medium: Jetpack Compose Toggle Button
Resource Roundup
100% pure code!
GitHub: krottv / compose-sliders
Vladislav Krot has released a library containing a SliderValueHorizontal()
composable for creating SeekBar
-style widgets, for users to select a value along
a range of values.
GitHub: atsushieno / compose-mpp
Atsushi Eno is creating a library to help fill in the gaps between Compose for Android
and Compose for Desktop, for where there are incompatibilities between their respective
APIs. Right now, it focuses on AlertDialog()
and DropdownMenu()
.
Gist: leonardoaramaki / Debouncer.kt
Leonardo Aramaki created a simple debounceClickable()
modifier to handle debouncing,
passing through debounced click events to your desired function or lambda.
GitHub: valentinilk / compose-shimmer
Shimmer effects are popular! Valentin Ilk has created another library to provide
shimmer effects for your composables, such as for use as a loading state, via a
shimmer()
modifier.
…And One More Thing
While the core of Compose UI was laid down in time for the 1.0.0
stable release
earlier this year, there are a lot of edge cases that we will need to address.
In some cases, such as better keyboard support, the edge cases probably need to be handled
directly in Compose UI. In other cases, outside developers might be able to come up with
working patterns without necessarily having to wait on official Compose changes.
One such edge case is support for custom content on external displays. Official Android support for this has been around since Android 4.2, though Google’s interest in it has risen and fallen over the years. So, for example, while Samsung generally supports external displays via USB-C/HDMI adapters, Google has avoided it on the Pixel series (though I do need to test the Pixel 6…).
The default behavior of connecting an external display is screen mirroring: whatever is on the phone screen also appears on the TV, monitor, projector, or whatever you are using for the external display. There are two officially supported options that apps can use to control what goes on that external display.
The first is to launch an activity on that external display, using ActivityOptions
.
This has been available since Android 8.0. The good news is that Compose UI should
work nicely with this – it is merely another activity, after all. The bad news
is that it behaves oddly, not honoring requests for landscape.
Since most external displays are locked to landscape, this is a problem.
The second is to use Presentation
. An Activity
can display a Presentation
, connecting
it with a particular external display. This seems to work better. However, Presentation
is a subclass of the framework’s Dialog
class. Normally, in Compose UI, we work with
composable abstractions around that sort of thing. So, we may need to see what bits of
those abstractions are useful for a composable Presentation
, in addition to setting
up all of the “plumbing” for detecting external displays.
I am anticipating a need for this in 2022, so I expect that I will be taking a shot at these things before too long, and I will aim to write up the results. But, my needs are purely for Android; ideally some official solution for this also handles Compose for Desktop and Kotlin/Multiplatform.
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?!?