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/or MultiModalInjectionScope, 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.

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.